You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1943 lines
72 KiB

8 years ago
8 years ago
8 years ago
8 years ago
  1. ####################################################################################
  2. #
  3. # write_project_tcl.tcl (write a Vivado project tcl script for re-creating project)
  4. #
  5. # Script created on 02/08/2013 by Raj Klair (Xilinx, Inc.)
  6. #
  7. # 2014.2 - v2.0 (rev 4)
  8. # * do not return value from main proc
  9. # * fixed bug with relative file path calculation (break from loop while comparing
  10. # directory elements of file paths for file to make relative to o/p script dir)
  11. # 2014.1 - v2.0 (rev 3)
  12. # * make source file paths relative to script output directory
  13. #
  14. # 2013.4 -
  15. # 2013.3 -
  16. # 2013.2 - v1.0 (rev 2)
  17. # * no change
  18. #
  19. # 2013.1 - v1.0 (rev 1)
  20. # * initial version
  21. #
  22. ####################################################################################
  23. #
  24. # Modified version to better support revision control.
  25. # Can be called as write_project_tcl_git from the tcl console in Vivado.
  26. #
  27. # Differences:
  28. #
  29. # 1. The project directory is now relative to the scripts location.
  30. # Project directory was relative to the tcl console current directory.
  31. #
  32. # 2. When recreating a project, the generated files will be put in a "work" directory
  33. # under the project directory. If the work exists already, it will be rewritten.
  34. #
  35. # 3. After recreating a project, the tcl console will change directory to the project directory.
  36. #
  37. # 4. No mention to the creation time of the project script, so that it is not different
  38. # every time it is generated.
  39. #
  40. ####################################################################################
  41. package require Vivado 1.2014.1
  42. namespace eval ::custom {
  43. namespace export write_project_tcl_git
  44. }
  45. namespace eval ::custom {
  46. proc write_project_tcl_git {args} {
  47. # Summary:
  48. # Export Tcl script for re-creating the current project
  49. # Argument Usage:
  50. # [-paths_relative_to <arg> = Script output directory path]: Override the reference directory variable for source file relative paths
  51. # [-target_proj_dir <arg> = Current project directory path]: Directory where the project needs to be restored
  52. # [-force]: Overwrite existing tcl script file
  53. # [-all_properties]: Write all properties (default & non-default) for the project object(s)
  54. # [-no_copy_sources]: Do not import sources even if they were local in the original project
  55. # [-absolute_path]: Make all file paths absolute wrt the original project directory
  56. # [-dump_project_info]: Write object values
  57. # file: Name of the tcl script file to generate
  58. # Return Value:
  59. # true (0) if success, false (1) otherwise
  60. # Categories: xilinxtclstore, projutils
  61. # reset global variables
  62. variable a_global_vars
  63. reset_global_vars
  64. # process options
  65. for {set i 0} {$i < [llength $args]} {incr i} {
  66. set option [string trim [lindex $args $i]]
  67. switch -regexp -- $option {
  68. "-paths_relative_to" { incr i;set a_global_vars(s_relative_to) [file normalize [lindex $args $i]] }
  69. "-target_proj_dir" { incr i;set a_global_vars(s_target_proj_dir) [lindex $args $i] }
  70. "-force" { set a_global_vars(b_arg_force) 1 }
  71. "-all_properties" { set a_global_vars(b_arg_all_props) 1 }
  72. "-no_copy_sources" { set a_global_vars(b_arg_no_copy_srcs) 1 }
  73. "-absolute_path" { set a_global_vars(b_absolute_path) 1 }
  74. "-dump_project_info" { set a_global_vars(b_arg_dump_proj_info) 1 }
  75. default {
  76. # is incorrect switch specified?
  77. if { [regexp {^-} $option] } {
  78. send_msg_id Vivado-projutils-001 ERROR "Unknown option '$option', please type 'write_project_tcl -help' for usage info.\n"
  79. return
  80. }
  81. set a_global_vars(script_file) $option
  82. }
  83. }
  84. }
  85. # script file is a must
  86. if { [string equal $a_global_vars(script_file) ""] } {
  87. send_msg_id Vivado-projutils-002 ERROR "Missing value for option 'file', please type 'write_project_tcl -help' for usage info.\n"
  88. return
  89. }
  90. # should not be a directory
  91. if { [file isdirectory $a_global_vars(script_file)] } {
  92. 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"
  93. return
  94. }
  95. # check extension
  96. if { [file extension $a_global_vars(script_file)] != ".tcl" } {
  97. set a_global_vars(script_file) $a_global_vars(script_file).tcl
  98. }
  99. set a_global_vars(script_file) [file normalize $a_global_vars(script_file)]
  100. # error if file directory path does not exist
  101. set file_path [file dirname $a_global_vars(script_file)]
  102. if { ! [file exists $file_path] } {
  103. set script_filename [file tail $a_global_vars(script_file)]
  104. 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"
  105. return
  106. }
  107. # recommend -force if file exists
  108. if { [file exists $a_global_vars(script_file)] && !$a_global_vars(b_arg_force) } {
  109. send_msg_id Vivado-projutils-004 ERROR "Tcl Script '$a_global_vars(script_file)' already exist. Use -force option to overwrite.\n"
  110. return
  111. }
  112. # set script file directory path
  113. set a_global_vars(s_path_to_script_dir) [file normalize $file_path]
  114. # now write
  115. if {[write_project_tcl_script]} {
  116. return
  117. }
  118. }
  119. }
  120. namespace eval ::custom {
  121. #
  122. # write_project_tcl tcl script argument & file handle vars
  123. #
  124. variable a_global_vars
  125. variable l_script_data [list]
  126. variable l_local_files [list]
  127. variable l_remote_files [list]
  128. variable b_project_board_set 0
  129. # set file types to filter
  130. variable l_filetype_filter [list]
  131. # Setup filter for non-user-settable filetypes
  132. set l_filetype_filter [list "ip" "ipx" "embedded design sources" "elf" "coefficient files" "configuration files" \
  133. "block diagrams" "block designs" "dsp design sources" "text" \
  134. "design checkpoint" "waveform configuration file"]
  135. # ip file extension types
  136. variable l_valid_ip_extns [list]
  137. set l_valid_ip_extns [list ".xci" ".bd" ".slx"]
  138. # set fileset types
  139. variable a_fileset_types
  140. set a_fileset_types {
  141. {{DesignSrcs} {srcset}}
  142. {{BlockSrcs} {blockset}}
  143. {{Constrs} {constrset}}
  144. {{SimulationSrcs} {simset}}
  145. }
  146. proc reset_global_vars {} {
  147. # Summary: initializes global namespace vars
  148. # This helper command is used to reset the variables used in the script.
  149. # Argument Usage:
  150. # none
  151. # Return Value:
  152. # None
  153. variable a_global_vars
  154. set a_global_vars(s_relative_to) {.}
  155. set a_global_vars(s_path_to_script_dir) ""
  156. set a_global_vars(s_target_proj_dir) ""
  157. set a_global_vars(b_arg_force) 0
  158. set a_global_vars(b_arg_no_copy_srcs) 0
  159. set a_global_vars(b_absolute_path) 0
  160. set a_global_vars(b_arg_all_props) 0
  161. set a_global_vars(b_arg_dump_proj_info) 0
  162. set a_global_vars(b_local_sources) 0
  163. set a_global_vars(curr_time) [clock format [clock seconds]]
  164. set a_global_vars(fh) 0
  165. set a_global_vars(dp_fh) 0
  166. set a_global_vars(def_val_fh) 0
  167. set a_global_vars(script_file) ""
  168. set l_script_data [list]
  169. set l_local_files [list]
  170. set l_remote_files [list]
  171. }
  172. proc write_project_tcl_script {} {
  173. # Summary: write project script
  174. # This helper command is used to script help.
  175. # Argument Usage:
  176. # none
  177. # Return Value:
  178. # true (0) if success, false (1) otherwise
  179. variable a_global_vars
  180. variable l_script_data
  181. variable l_remote_files
  182. variable l_local_files
  183. set l_script_data [list]
  184. set l_local_files [list]
  185. set l_remote_files [list]
  186. # get the project name
  187. set tcl_obj [current_project]
  188. set proj_name [file tail [get_property name $tcl_obj]]
  189. set proj_dir [get_property directory $tcl_obj]
  190. set part_name [get_property part $tcl_obj]
  191. # output file script handle
  192. set file $a_global_vars(script_file)
  193. if {[catch {open $file w} a_global_vars(fh)]} {
  194. send_msg_id Vivado-projutils-005 ERROR "failed to open file for write ($file)\n"
  195. return 1
  196. }
  197. # dump project in canonical form
  198. if { $a_global_vars(b_arg_dump_proj_info) } {
  199. set dump_file [file normalize [file join $a_global_vars(s_path_to_script_dir) ${proj_name}_dump.txt]]
  200. if {[catch {open $dump_file w} a_global_vars(dp_fh)]} {
  201. send_msg_id Vivado-projutils-006 ERROR "failed to open file for write ($dump_file)\n"
  202. return 1
  203. }
  204. # default value output file script handle
  205. set def_val_file [file normalize [file join $a_global_vars(s_path_to_script_dir) ${proj_name}_def_val.txt]]
  206. if {[catch {open $def_val_file w} a_global_vars(def_val_fh)]} {
  207. send_msg_id Vivado-projutils-007 ERROR "failed to open file for write ($file)\n"
  208. return 1
  209. }
  210. }
  211. # explicitly update the compile order for current source/simset, if following conditions are met
  212. if { {All} == [get_property source_mgmt_mode [current_project]] &&
  213. {0} == [get_property is_readonly [current_project]] &&
  214. {RTL} == [get_property design_mode [current_fileset]] } {
  215. # re-parse source fileset compile order for the current top
  216. if {[llength [get_files -compile_order sources -used_in synthesis]] > 1} {
  217. update_compile_order -fileset [current_fileset] -quiet
  218. }
  219. # re-parse simlulation fileset compile order for the current top
  220. if {[llength [get_files -compile_order sources -used_in simulation]] > 1} {
  221. update_compile_order -fileset [current_fileset -simset] -quiet
  222. }
  223. }
  224. # writer helpers
  225. wr_create_project $proj_dir $proj_name $part_name
  226. wr_project_properties $proj_dir $proj_name
  227. wr_filesets $proj_dir $proj_name
  228. wr_runs $proj_dir $proj_name
  229. wr_proj_info $proj_name
  230. # write header
  231. write_header $proj_dir $proj_name $file
  232. # write script data
  233. foreach line $l_script_data {
  234. puts $a_global_vars(fh) $line
  235. }
  236. close $a_global_vars(fh)
  237. if { $a_global_vars(b_arg_dump_proj_info) } {
  238. close $a_global_vars(def_val_fh)
  239. close $a_global_vars(dp_fh)
  240. }
  241. set script_filename [file tail $file]
  242. set out_dir [file dirname [file normalize $file]]
  243. send_msg_id Vivado-projutils-008 INFO "Tcl script '$script_filename' generated in output directory '$out_dir'\n\n"
  244. if { $a_global_vars(b_absolute_path) } {
  245. 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\
  246. 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."
  247. } else {
  248. if { "." != $a_global_vars(s_relative_to) } {
  249. 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\
  250. wrt the path that was specified with this switch. The 'origin_dir' variable is set to this path in the generated script."
  251. } else {
  252. 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\
  253. generated script. When this script is executed from the output directory, these source files will be referenced wrt this 'origin_dir' path value.\n\
  254. 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\
  255. 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\
  256. 'origin_dir' automatically by setting the 'origin_dir_loc' variable in the tcl shell before sourcing this generated script. The 'origin_dir_loc'\n\
  257. 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\
  258. then set the origin dir using '-tclargs --origin_dir <path>'. For example, 'vivado -mode tcl -source $script_filename -tclargs --origin_dir \"..\"\n"
  259. }
  260. }
  261. if { $a_global_vars(b_local_sources) } {
  262. print_local_file_msg "warning"
  263. } else {
  264. print_local_file_msg "info"
  265. }
  266. reset_global_vars
  267. return 0
  268. }
  269. proc wr_create_project { proj_dir name part_name } {
  270. # Summary: write create project command
  271. # This helper command is used to script help.
  272. # Argument Usage:
  273. # proj_dir: project directory path
  274. # name: project name
  275. # Return Value:
  276. # none
  277. variable a_global_vars
  278. variable l_script_data
  279. lappend l_script_data "# Set the reference directory for source file relative paths (by default the value is script directory path)"
  280. lappend l_script_data "set origin_dir \[file dirname \[info script\]\]"
  281. lappend l_script_data ""
  282. set var_name "origin_dir_loc"
  283. lappend l_script_data "# Use origin directory path location variable, if specified in the tcl shell"
  284. lappend l_script_data "if \{ \[info exists ::$var_name\] \} \{"
  285. lappend l_script_data " set origin_dir \$::$var_name"
  286. lappend l_script_data "\}"
  287. lappend l_script_data ""
  288. lappend l_script_data "variable script_file"
  289. lappend l_script_data "set script_file \"[file tail $a_global_vars(script_file)]\"\n"
  290. lappend l_script_data "# Help information for this script"
  291. lappend l_script_data "proc help \{\} \{"
  292. lappend l_script_data " variable script_file"
  293. lappend l_script_data " puts \"\\nDescription:\""
  294. lappend l_script_data " puts \"Recreate a Vivado project from this script. The created project will be\""
  295. lappend l_script_data " puts \"functionally equivalent to the original project for which this script was\""
  296. lappend l_script_data " puts \"generated. The script contains commands for creating a project, filesets,\""
  297. lappend l_script_data " puts \"runs, adding/importing sources and setting properties on various objects.\\n\""
  298. lappend l_script_data " puts \"Syntax:\""
  299. lappend l_script_data " puts \"\$script_file\""
  300. lappend l_script_data " puts \"\$script_file -tclargs \\\[--origin_dir <path>\\\]\""
  301. lappend l_script_data " puts \"\$script_file -tclargs \\\[--help\\\]\\n\""
  302. lappend l_script_data " puts \"Usage:\""
  303. lappend l_script_data " puts \"Name Description\""
  304. lappend l_script_data " puts \"-------------------------------------------------------------------------\""
  305. lappend l_script_data " puts \"\\\[--origin_dir <path>\\\] Determine source file paths wrt this path. Default\""
  306. lappend l_script_data " puts \" origin_dir path value is \\\".\\\", otherwise, the value\""
  307. lappend l_script_data " puts \" that was set with the \\\"-paths_relative_to\\\" switch\""
  308. lappend l_script_data " puts \" when this script was generated.\\n\""
  309. lappend l_script_data " puts \"\\\[--help\\\] Print help information for this script\""
  310. lappend l_script_data " puts \"-------------------------------------------------------------------------\\n\""
  311. lappend l_script_data " exit 0"
  312. lappend l_script_data "\}\n"
  313. lappend l_script_data "if \{ \$::argc > 0 \} \{"
  314. lappend l_script_data " for \{set i 0\} \{\$i < \[llength \$::argc\]\} \{incr i\} \{"
  315. lappend l_script_data " set option \[string trim \[lindex \$::argv \$i\]\]"
  316. lappend l_script_data " switch -regexp -- \$option \{"
  317. lappend l_script_data " \"--origin_dir\" \{ incr i; set origin_dir \[lindex \$::argv \$i\] \}"
  318. lappend l_script_data " \"--help\" \{ help \}"
  319. lappend l_script_data " default \{"
  320. lappend l_script_data " if \{ \[regexp \{^-\} \$option\] \} \{"
  321. lappend l_script_data " puts \"ERROR: Unknown option '\$option' specified, please type '\$script_file -tclargs --help' for usage info.\\n\""
  322. lappend l_script_data " return 1"
  323. lappend l_script_data " \}"
  324. lappend l_script_data " \}"
  325. lappend l_script_data " \}"
  326. lappend l_script_data " \}"
  327. lappend l_script_data "\}\n"
  328. lappend l_script_data "# Set the directory path for the original project from where this script was exported"
  329. if { $a_global_vars(b_absolute_path) } {
  330. lappend l_script_data "set orig_proj_dir \"$proj_dir\""
  331. } else {
  332. set rel_file_path "[get_relative_file_path_for_source $proj_dir [get_script_execution_dir]]"
  333. set path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
  334. lappend l_script_data "set orig_proj_dir \"$path\""
  335. }
  336. lappend l_script_data ""
  337. # create project
  338. lappend l_script_data "# Create project"
  339. set tcl_cmd ""
  340. # set target project directory path if specified. If not, create project dir in current dir.
  341. set target_dir $a_global_vars(s_target_proj_dir)
  342. if { {} == $target_dir } {
  343. set tcl_cmd "create_project $name \$origin_dir/work -part $part_name -quiet -force"
  344. } else {
  345. # is specified target proj dir == current dir?
  346. set cwd [file normalize [string map {\\ /} [pwd]]]
  347. set dir [file normalize [string map {\\ /} $target_dir]]
  348. if { [string equal $cwd $dir] } {
  349. set tcl_cmd "create_project $name -part $part_name"
  350. } else {
  351. set tcl_cmd "create_project $name \"$target_dir\" -part $part_name"
  352. }
  353. }
  354. if { [get_property managed_ip [current_project]] } {
  355. set tcl_cmd "$tcl_cmd -ip"
  356. }
  357. lappend l_script_data $tcl_cmd
  358. if { $a_global_vars(b_arg_dump_proj_info) } {
  359. puts $a_global_vars(dp_fh) "project_name=$name"
  360. }
  361. lappend l_script_data ""
  362. lappend l_script_data "# Set the directory path for the new project"
  363. lappend l_script_data "set proj_dir \[get_property directory \[current_project\]\]"
  364. lappend l_script_data ""
  365. lappend l_script_data "# Reconstruct message rules"
  366. set msg_control_rules [ debug::get_msg_control_rules -as_tcl ]
  367. if { [string length $msg_control_rules] > 0 } {
  368. lappend l_script_data "${msg_control_rules}"
  369. } else {
  370. lappend l_script_data "# None"
  371. }
  372. lappend l_script_data ""
  373. }
  374. proc wr_project_properties { proj_dir proj_name } {
  375. # Summary: write project properties
  376. # This helper command is used to script help.
  377. # Argument Usage:
  378. # proj_name: project name
  379. # Return Value:
  380. # None
  381. variable l_script_data
  382. variable b_project_board_set
  383. # write project properties
  384. set tcl_obj [current_project]
  385. set get_what "get_projects"
  386. lappend l_script_data "# Set project properties"
  387. lappend l_script_data "set obj \[$get_what $tcl_obj\]"
  388. # is project "board_part" set already?
  389. if { [string length [get_property "board_part" $tcl_obj]] > 0 } {
  390. set b_project_board_set 1
  391. }
  392. write_props $proj_dir $proj_name $get_what $tcl_obj "project"
  393. }
  394. proc wr_filesets { proj_dir proj_name } {
  395. # Summary: write fileset object properties
  396. # This helper command is used to script help.
  397. # Argument Usage:
  398. # proj_name: project name
  399. # Return Value:
  400. # None
  401. variable a_fileset_types
  402. # write fileset data
  403. foreach {fs_data} $a_fileset_types {
  404. set filesets [get_filesets -filter FILESET_TYPE==[lindex $fs_data 0]]
  405. write_specified_fileset $proj_dir $proj_name $filesets
  406. }
  407. }
  408. proc write_specified_fileset { proj_dir proj_name filesets } {
  409. # Summary: write fileset properties and sources
  410. # This helper command is used to script help.
  411. # Argument Usage:
  412. # proj_name: project name
  413. # filesets: list of filesets
  414. # Return Value:
  415. # None
  416. variable a_global_vars
  417. variable l_script_data
  418. variable a_fileset_types
  419. # write filesets
  420. set type "file"
  421. foreach tcl_obj $filesets {
  422. # Is this a IP block fileset for a proxy IP that is owned by another composite file?
  423. # If so, we don't want to write it out as an independent file. The parent will take care of it.
  424. if { [is_proxy_ip_fileset $tcl_obj] } {
  425. continue
  426. }
  427. set fs_type [get_property fileset_type [get_filesets $tcl_obj]]
  428. # is this a IP block fileset? if yes, do not create block fileset, but create for a pure HDL based fileset (no IP's)
  429. if { [is_ip_fileset $tcl_obj] } {
  430. # do not create block fileset
  431. } else {
  432. lappend l_script_data "# Create '$tcl_obj' fileset (if not found)"
  433. lappend l_script_data "if \{\[string equal \[get_filesets -quiet $tcl_obj\] \"\"\]\} \{"
  434. set fs_sw_type [get_fileset_type_switch $fs_type]
  435. lappend l_script_data " create_fileset $fs_sw_type $tcl_obj"
  436. lappend l_script_data "\}\n"
  437. }
  438. set get_what_fs "get_filesets"
  439. # set IP REPO PATHS (if any) for filesets of type "DesignSrcs" or "BlockSrcs"
  440. if { (({DesignSrcs} == $fs_type) || ({BlockSrcs} == $fs_type)) } {
  441. # If BlockSet contains only one IP, then this indicates the case of OOC1
  442. # This means that we should not write these properties, they are read-only
  443. set blockset_is_ooc1 false
  444. if { {BlockSrcs} == $fs_type } {
  445. set current_fs_files [get_files -of_objects [get_filesets $tcl_obj] -norecurse]
  446. if { [llength $current_fs_files] == 1 } {
  447. set only_file_in_fs [lindex $current_fs_files 0]
  448. set file_type [get_property FILE_TYPE $only_file_in_fs]
  449. set blockset_is_ooc1 [expr {$file_type == {IP}} ? true : false]
  450. }
  451. }
  452. if { $blockset_is_ooc1} {
  453. # We do not write properties for OOC1
  454. } elseif { ({RTL} == [get_property design_mode [get_filesets $tcl_obj]]) } {
  455. set repo_paths [get_ip_repo_paths $tcl_obj]
  456. if { [llength $repo_paths] > 0 } {
  457. lappend l_script_data "# Set IP repository paths"
  458. lappend l_script_data "set obj \[get_filesets $tcl_obj\]"
  459. set path_list [list]
  460. foreach path $repo_paths {
  461. if { $a_global_vars(b_absolute_path) } {
  462. lappend path_list $path
  463. } else {
  464. set rel_file_path "[get_relative_file_path_for_source $path [get_script_execution_dir]]"
  465. set path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
  466. lappend path_list $path
  467. }
  468. }
  469. set repo_path_str [join $path_list " "]
  470. lappend l_script_data "set_property \"ip_repo_paths\" \"${repo_path_str}\" \$obj"
  471. lappend l_script_data ""
  472. lappend l_script_data "# Rebuild user ip_repo's index before adding any source files"
  473. lappend l_script_data "update_ip_catalog -rebuild"
  474. lappend l_script_data ""
  475. }
  476. }
  477. }
  478. # is this a IP block fileset? if yes, then set the current srcset object (IP's will be added to current source fileset)
  479. if { [is_ip_fileset $tcl_obj] } {
  480. set srcset [current_fileset -srcset]
  481. lappend l_script_data "# Set '$srcset' fileset object"
  482. lappend l_script_data "set obj \[$get_what_fs $srcset\]"
  483. } else {
  484. lappend l_script_data "# Set '$tcl_obj' fileset object"
  485. lappend l_script_data "set obj \[$get_what_fs $tcl_obj\]"
  486. }
  487. if { {Constrs} == $fs_type } {
  488. lappend l_script_data ""
  489. write_constrs $proj_dir $proj_name $tcl_obj $type
  490. } else {
  491. write_files $proj_dir $proj_name $tcl_obj $type
  492. }
  493. # is this a IP block fileset? if yes, do not write block fileset properties (block fileset doesnot exist in new project)
  494. if { [is_ip_fileset $tcl_obj] } {
  495. # do not write ip fileset properties
  496. } else {
  497. lappend l_script_data "# Set '$tcl_obj' fileset properties"
  498. lappend l_script_data "set obj \[$get_what_fs $tcl_obj\]"
  499. write_props $proj_dir $proj_name $get_what_fs $tcl_obj "fileset"
  500. }
  501. }
  502. }
  503. proc wr_runs { proj_dir proj_name } {
  504. # Summary: write runs and properties
  505. # This helper command is used to script help.
  506. # Argument Usage:
  507. # proj_name: project name
  508. # Return Value:
  509. # None
  510. variable l_script_data
  511. # write runs (synthesis, Implementation)
  512. set runs [get_runs -filter {IS_SYNTHESIS == 1}]
  513. write_specified_run $proj_dir $proj_name $runs
  514. if { {RTL} == [get_property design_mode [current_fileset]] } {
  515. lappend l_script_data "# set the current synth run"
  516. lappend l_script_data "current_run -synthesis \[get_runs [current_run -synthesis]\]\n"
  517. }
  518. set runs [get_runs -filter {IS_IMPLEMENTATION == 1}]
  519. write_specified_run $proj_dir $proj_name $runs
  520. lappend l_script_data "# set the current impl run"
  521. lappend l_script_data "current_run -implementation \[get_runs [current_run -implementation]\]"
  522. lappend l_script_data ""
  523. lappend l_script_data "# Change current directory to project folder"
  524. lappend l_script_data "cd \[file dirname \[info script\]\]"
  525. }
  526. proc wr_proj_info { proj_name } {
  527. # Summary: write generated project status message
  528. # This helper command is used to script help.
  529. # Argument Usage:
  530. # proj_name: project name
  531. # Return Value:
  532. # None
  533. variable l_script_data
  534. lappend l_script_data "\nputs \"INFO: Project created:$proj_name\""
  535. }
  536. proc write_header { proj_dir proj_name file } {
  537. # Summary: write script header
  538. # This helper command is used to script help.
  539. # Argument Usage:
  540. # Return Value:
  541. # None
  542. variable a_global_vars
  543. variable l_local_files
  544. variable l_remote_files
  545. set version_txt [split [version] "\n"]
  546. set version [lindex $version_txt 0]
  547. set copyright [lindex $version_txt 2]
  548. set product [lindex [split $version " "] 0]
  549. set version_id [join [lrange $version 1 end] " "]
  550. set tcl_file [file tail $file]
  551. puts $a_global_vars(fh) "#\n# $product (TM) $version_id"
  552. puts $a_global_vars(fh) "#\n# $tcl_file: Tcl script for re-creating project '$proj_name'\n#"
  553. puts $a_global_vars(fh) "# $copyright"
  554. puts $a_global_vars(fh) "#\n# This file contains the $product Tcl commands for re-creating the project to the state*"
  555. puts $a_global_vars(fh) "# when this script was generated. In order to re-create the project, please source this"
  556. puts $a_global_vars(fh) "# file in the $product Tcl Shell."
  557. puts $a_global_vars(fh) "#"
  558. puts $a_global_vars(fh) "# * Note that the runs in the created project will be configured the same way as the"
  559. puts $a_global_vars(fh) "# original project, however they will not be launched automatically. To regenerate the"
  560. puts $a_global_vars(fh) "# run results please launch the synthesis/implementation runs as needed.\n#"
  561. puts $a_global_vars(fh) "#*****************************************************************************************"
  562. puts $a_global_vars(fh) "# NOTE: In order to use this script for source control purposes, please make sure that the"
  563. puts $a_global_vars(fh) "# following files are added to the source control system:-"
  564. puts $a_global_vars(fh) "#"
  565. puts $a_global_vars(fh) "# 1. This project restoration tcl script (${tcl_file}) that was generated."
  566. puts $a_global_vars(fh) "#"
  567. puts $a_global_vars(fh) "# 2. The following source(s) files that were local or imported into the original project."
  568. puts $a_global_vars(fh) "# (Please see the '\$orig_proj_dir' and '\$origin_dir' variable setting below at the start of the script)\n#"
  569. if {[llength $l_local_files] == 0} {
  570. puts $a_global_vars(fh) "# <none>"
  571. } else {
  572. foreach line $l_local_files {
  573. puts $a_global_vars(fh) "# $line"
  574. }
  575. }
  576. puts $a_global_vars(fh) "#"
  577. puts $a_global_vars(fh) "# 3. The following remote source files that were added to the original project:-\n#"
  578. if {[llength $l_remote_files] == 0} {
  579. puts $a_global_vars(fh) "# <none>"
  580. } else {
  581. foreach line $l_remote_files {
  582. puts $a_global_vars(fh) "# $line"
  583. }
  584. }
  585. puts $a_global_vars(fh) "#"
  586. puts $a_global_vars(fh) "#*****************************************************************************************\n"
  587. }
  588. proc print_local_file_msg { msg_type } {
  589. # Summary: print warning on finding local sources
  590. # This helper command is used to script help.
  591. # Argument Usage:
  592. # Return Value:
  593. # None
  594. puts ""
  595. if { [string equal $msg_type "warning"] } {
  596. 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\
  597. 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\
  598. under the header section."
  599. } else {
  600. 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\
  601. controlled data. The list of these local source(s) can be found in the generated script under the header section."
  602. }
  603. puts ""
  604. }
  605. proc get_ip_repo_paths { tcl_obj } {
  606. # Summary:
  607. # Iterate over the fileset properties and get the ip_repo_paths (if set)
  608. # Argument Usage:
  609. # tcl_obj : fileset
  610. # Return Value:
  611. # List of repo paths
  612. set repo_path_list [list]
  613. foreach path [get_property ip_repo_paths [get_filesets $tcl_obj]] {
  614. lappend repo_path_list $path
  615. }
  616. return $repo_path_list
  617. }
  618. proc is_deprecated { prop } {
  619. # Summary: filter deprecated properties
  620. # Argument Usage:
  621. # Return Value:
  622. # true (1) if found, false (1) otherwise
  623. set prop [string toupper $prop]
  624. if { $prop == "BOARD" } {
  625. return 1
  626. }
  627. return 0
  628. }
  629. proc filter { prop val { file {} } } {
  630. # Summary: filter special properties
  631. # This helper command is used to script help.
  632. # Argument Usage:
  633. # Return Value:
  634. # true (1) if found, false (1) otherwise
  635. variable l_filetype_filter
  636. variable l_valid_ip_extns
  637. set prop [string toupper $prop]
  638. if { [expr { $prop == "BOARD" } || \
  639. { $prop == "IS_HD" } || \
  640. { $prop == "IS_PARTIAL_RECONFIG" } || \
  641. { $prop == "ADD_STEP" }]} {
  642. return 1
  643. }
  644. if { [string equal type "project"] } {
  645. if { [expr { $prop == "DIRECTORY" }] } {
  646. return 1
  647. }
  648. }
  649. # error reported if file_type is set
  650. # e.g ERROR: [Vivado 12-563] The file type 'IP' is not user settable.
  651. set val [string tolower $val]
  652. if { [string equal $prop "FILE_TYPE"] } {
  653. if { [lsearch $l_filetype_filter $val] != -1 } {
  654. return 1
  655. }
  656. }
  657. # filter readonly is_managed property for ip
  658. if { [string equal $prop "IS_MANAGED"] } {
  659. if { [lsearch -exact $l_valid_ip_extns [string tolower [file extension $file]]] >= 0 } {
  660. return 1
  661. }
  662. }
  663. # filter ip_repo_paths (ip_repo_paths is set before adding sources)
  664. if { [string equal -nocase $prop {ip_repo_paths}] } {
  665. return 1
  666. }
  667. return 0
  668. }
  669. proc is_local_to_project { file } {
  670. # Summary: check if file is local to the project directory structure
  671. # This helper command is used to script help.
  672. # Argument Usage:
  673. # Return Value:
  674. # true (1), if file is local to the project (inside project directory structure)
  675. # false (0), if file is outside the project directory structure
  676. set dir [get_property directory [current_project]]
  677. set proj_comps [split [string trim [file normalize [string map {\\ /} $dir]]] "/"]
  678. set file_comps [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  679. set is_local 1
  680. for {set i 1} {$i < [llength $proj_comps]} {incr i} {
  681. if { [lindex $proj_comps $i] != [lindex $file_comps $i] } {
  682. set is_local 0;break
  683. }
  684. }
  685. return $is_local
  686. }
  687. proc is_ip_readonly_prop { name } {
  688. # Summary: Return true if dealing with following IP properties that are not settable for an IP in read-only state
  689. # Argument Usage:
  690. # name: property name
  691. # Return Value:
  692. # true if success, false otherwise
  693. if { [regexp -nocase {synth_checkpoint_mode} $name] ||
  694. [regexp -nocase {is_locked} $name] ||
  695. [regexp -nocase {generate_synth_checkpoint} $name] } {
  696. return true
  697. }
  698. return false
  699. }
  700. proc write_properties { prop_info_list get_what tcl_obj } {
  701. # Summary: write object properties
  702. # This helper command is used to script help.
  703. # Argument Usage:
  704. # Return Value:
  705. # None
  706. variable a_global_vars
  707. variable l_script_data
  708. if {[llength $prop_info_list] > 0} {
  709. set b_add_closing_brace 0
  710. foreach x $prop_info_list {
  711. set elem [split $x "#"]
  712. set name [lindex $elem 0]
  713. set value [lindex $elem 1]
  714. if { [regexp "more options" $name] } {
  715. set cmd_str "set_property -name {$name} -value {$value} -objects"
  716. } elseif { ([is_ip_readonly_prop $name]) && ([string equal $get_what "get_files"]) } {
  717. set cmd_str "if \{ !\[get_property \"is_locked\" \$file_obj\] \} \{"
  718. lappend l_script_data "$cmd_str"
  719. set cmd_str " set_property \"$name\" \"$value\""
  720. set b_add_closing_brace 1
  721. } else {
  722. set cmd_str "set_property \"$name\" \"$value\""
  723. }
  724. if { [string equal $get_what "get_files"] } {
  725. lappend l_script_data "$cmd_str \$file_obj"
  726. if { $b_add_closing_brace } {
  727. lappend l_script_data "\}"
  728. set b_add_closing_brace 0
  729. }
  730. } else {
  731. # comment "is_readonly" project property
  732. if { [string equal $get_what "get_projects"] && [string equal "$name" "is_readonly"] } {
  733. if { ! $a_global_vars(b_arg_all_props) } {
  734. send_msg_id Vivado-projutils-012 INFO "The current project is in 'read_only' state. The generated script will create a writable project."
  735. }
  736. continue
  737. }
  738. lappend l_script_data "$cmd_str \$obj"
  739. }
  740. }
  741. }
  742. lappend l_script_data ""
  743. }
  744. proc write_props { proj_dir proj_name get_what tcl_obj type } {
  745. # Summary: write first class object properties
  746. # This helper command is used to script help.
  747. # Argument Usage:
  748. # Return Value:
  749. # none
  750. variable a_global_vars
  751. variable l_script_data
  752. variable b_project_board_set
  753. set obj_name [get_property name [$get_what $tcl_obj]]
  754. set read_only_props [rdi::get_attr_specs -class [get_property class $tcl_obj] -filter {is_readonly}]
  755. set prop_info_list [list]
  756. set properties [list_property [$get_what $tcl_obj]]
  757. foreach prop $properties {
  758. if { [is_deprecated $prop] } { continue }
  759. # skip read-only properties
  760. if { [lsearch $read_only_props $prop] != -1 } { continue }
  761. set prop_type "unknown"
  762. if { [string equal $type "run"] } {
  763. if { [regexp "STEPS" $prop] } {
  764. # skip step properties
  765. } else {
  766. set attr_names [rdi::get_attr_specs -class [get_property class [get_runs $tcl_obj] ]]
  767. if { [lsearch $attr_names $prop] != -1 } {
  768. set prop_type [get_property type [lindex $attr_names [lsearch $attr_names $prop]]]
  769. }
  770. }
  771. } else {
  772. set attr_spec [rdi::get_attr_specs -quiet $prop -object [$get_what $tcl_obj]]
  773. if { {} == $attr_spec } {
  774. set prop_lower [string tolower $prop]
  775. set attr_spec [rdi::get_attr_specs -quiet $prop_lower -object [$get_what $tcl_obj]]
  776. }
  777. set prop_type [get_property type $attr_spec]
  778. }
  779. set def_val [list_property_value -default $prop $tcl_obj]
  780. set dump_prop_name [string tolower ${obj_name}_${type}_$prop]
  781. set cur_val [get_property $prop $tcl_obj]
  782. # filter special properties
  783. if { [filter $prop $cur_val] } { continue }
  784. # do not set "runs" or "project" part, if "board_part" is set
  785. if { ([string equal $type "project"] || [string equal $type "run"]) &&
  786. [string equal -nocase $prop "part"] &&
  787. $b_project_board_set } {
  788. continue
  789. }
  790. # do not set "fileset" target_part, if "board_part" is set
  791. if { [string equal $type "fileset"] &&
  792. [string equal -nocase $prop "target_part"] &&
  793. $b_project_board_set } {
  794. continue
  795. }
  796. # re-align values
  797. set cur_val [get_target_bool_val $def_val $cur_val]
  798. set prop_entry "[string tolower $prop]#[get_property $prop [$get_what $tcl_obj]]"
  799. # fix paths wrt the original project dir
  800. if {([string equal -nocase $prop "top_file"]) && ($cur_val != "") } {
  801. set file $cur_val
  802. set srcs_dir "${proj_name}.srcs"
  803. set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  804. set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
  805. if { [is_local_to_project $file] } {
  806. set proj_file_path "\$proj_dir/$src_file"
  807. } else {
  808. set proj_file_path "[get_relative_file_path_for_source $src_file [get_script_execution_dir]]"
  809. }
  810. set prop_entry "[string tolower $prop]#$proj_file_path"
  811. } elseif {([string equal -nocase $prop "target_constrs_file"] ||
  812. [string equal -nocase $prop "target_ucf"]) &&
  813. ($cur_val != "") } {
  814. set file $cur_val
  815. set fs_name $tcl_obj
  816. set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  817. set src_file [join [lrange $path_dirs [lsearch -exact $path_dirs "$fs_name"] end] "/"]
  818. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
  819. set file_props [list_property $file_object]
  820. if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
  821. if { $a_global_vars(b_arg_no_copy_srcs) } {
  822. set proj_file_path "\$orig_proj_dir/${proj_name}.srcs/$src_file"
  823. } else {
  824. set proj_file_path "\$proj_dir/${proj_name}.srcs/$src_file"
  825. }
  826. } else {
  827. # is file new inside project?
  828. if { [is_local_to_project $file] } {
  829. # is file inside fileset dir?
  830. if { [regexp "^${fs_name}/" $src_file] } {
  831. set proj_file_path "\$orig_proj_dir/${proj_name}.srcs/$src_file"
  832. } else {
  833. set file_no_quotes [string trim $file "\""]
  834. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  835. set proj_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
  836. #set proj_file_path "$file"
  837. }
  838. } else {
  839. if { $a_global_vars(b_absolute_path) } {
  840. set proj_file_path "$file"
  841. } else {
  842. set file_no_quotes [string trim $file "\""]
  843. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  844. set proj_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
  845. }
  846. }
  847. }
  848. set prop_entry "[string tolower $prop]#$proj_file_path"
  849. }
  850. # re-align compiled_library_dir
  851. if { [string equal -nocase $prop "compxlib.compiled_library_dir"] ||
  852. [string equal -nocase $prop "compxlib.modelsim_compiled_library_dir"] ||
  853. [string equal -nocase $prop "compxlib.questa_compiled_library_dir"] ||
  854. [string equal -nocase $prop "compxlib.ies_compiled_library_dir"] ||
  855. [string equal -nocase $prop "compxlib.vcs_compiled_library_dir"] ||
  856. [string equal -nocase $prop "compxlib.riviera_compiled_library_dir"] ||
  857. [string equal -nocase $prop "compxlib.activehdl_compiled_library_dir"] } {
  858. set compile_lib_dir_path $cur_val
  859. set cache_dir "${proj_name}.cache"
  860. set path_dirs [split [string trim [file normalize [string map {\\ /} $cur_val]]] "/"]
  861. if {[lsearch -exact $path_dirs "$cache_dir"] > 0} {
  862. set dir_path [join [lrange $path_dirs [lsearch -exact $path_dirs "$cache_dir"] end] "/"]
  863. set compile_lib_dir_path "\$proj_dir/$dir_path"
  864. }
  865. set prop_entry "[string tolower $prop]#$compile_lib_dir_path"
  866. }
  867. # process run step tcl pre/post properties
  868. if { [string equal $type "run"] } {
  869. if { [regexp "STEPS" $prop] } {
  870. if { [regexp "TCL.PRE" $prop] || [regexp "TCL.POST" $prop] } {
  871. if { ($cur_val != "") } {
  872. set file $cur_val
  873. set srcs_dir "${proj_name}.srcs"
  874. set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  875. set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
  876. set tcl_file_path {}
  877. if { [is_local_to_project $file] } {
  878. set tcl_file_path "\$proj_dir/$src_file"
  879. } else {
  880. if { $a_global_vars(b_absolute_path) } {
  881. set tcl_file_path "$file"
  882. } else {
  883. set rel_file_path "[get_relative_file_path_for_source $src_file [get_script_execution_dir]]"
  884. set tcl_file_path "\[file normalize \"\$origin_dir/$rel_file_path\"\]"
  885. }
  886. }
  887. set prop_entry "[string tolower $prop]#$tcl_file_path"
  888. }
  889. }
  890. }
  891. }
  892. if { $a_global_vars(b_arg_all_props) } {
  893. lappend prop_info_list $prop_entry
  894. } else {
  895. if { $def_val != $cur_val } {
  896. lappend prop_info_list $prop_entry
  897. }
  898. }
  899. if { $a_global_vars(b_arg_dump_proj_info) } {
  900. if { ([string equal -nocase $prop "top_file"] ||
  901. [string equal -nocase $prop "target_constrs_file"] ||
  902. [string equal -nocase $prop "target_ucf"] ) && [string equal $type "fileset"] } {
  903. # fix path
  904. set file $cur_val
  905. set srcs_dir "${proj_name}.srcs"
  906. set file_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  907. set src_file [join [lrange $file_dirs [lsearch -exact $file_dirs "$srcs_dir"] end] "/"]
  908. set cur_val "\$PSRCDIR/$src_file"
  909. }
  910. puts $a_global_vars(def_val_fh) "$prop:($prop_type) DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
  911. puts $a_global_vars(dp_fh) "${dump_prop_name}=$cur_val"
  912. }
  913. }
  914. if { {fileset} == $type } {
  915. set fs_type [get_property fileset_type [get_filesets $tcl_obj]]
  916. if { {SimulationSrcs} == $fs_type } {
  917. if { ![get_property is_readonly [current_project]] } {
  918. add_simulator_props $get_what $tcl_obj prop_info_list
  919. }
  920. }
  921. }
  922. # write properties now
  923. write_properties $prop_info_list $get_what $tcl_obj
  924. }
  925. proc add_simulator_props { get_what tcl_obj prop_info_list_arg } {
  926. # Summary: write file and file properties
  927. # This helper command is used to script help.
  928. # Argument Usage:
  929. # Return Value:
  930. # none
  931. upvar $prop_info_list_arg prop_info_list
  932. set target_simulator [get_property target_simulator [current_project]]
  933. set simulators [get_simulators]
  934. foreach simulator [get_simulators] {
  935. if { $target_simulator == $simulator } { continue }
  936. set_property target_simulator $simulator [current_project]
  937. set prefix [string tolower [lindex [split $simulator {.}] 0]]
  938. write_simulator_props $prefix $get_what $tcl_obj prop_info_list
  939. }
  940. set_property target_simulator $target_simulator [current_project]
  941. }
  942. proc write_simulator_props { prefix get_what tcl_obj prop_info_list_arg } {
  943. # Summary: write non-default simulator properties
  944. # Argument Usage:
  945. # Return Value:
  946. # none
  947. upvar $prop_info_list_arg prop_info_list
  948. variable a_global_vars
  949. variable l_script_data
  950. set read_only_props [rdi::get_attr_specs -class [get_property class $tcl_obj] -filter {is_readonly}]
  951. foreach prop [list_property [$get_what $tcl_obj]] {
  952. if { [lsearch $read_only_props $prop] != -1 } { continue }
  953. if { [is_deprecated_property $prop] } { continue }
  954. set sim_prefix [string tolower [lindex [split $prop {.}] 0]]
  955. if { $prefix != $sim_prefix } { continue }
  956. set attr_spec [rdi::get_attr_specs -quiet $prop -object [$get_what $tcl_obj]]
  957. if { {} == $attr_spec } {
  958. set prop_lower [string tolower $prop]
  959. set attr_spec [rdi::get_attr_specs -quiet $prop_lower -object [$get_what $tcl_obj]]
  960. }
  961. set prop_type [get_property type $attr_spec]
  962. set def_val [list_property_value -default $prop $tcl_obj]
  963. set cur_val [get_property $prop $tcl_obj]
  964. set cur_val [get_target_bool_val $def_val $cur_val]
  965. set prop_entry "[string tolower $prop]#[get_property $prop [$get_what $tcl_obj]]"
  966. if { $def_val != $cur_val } {
  967. lappend prop_info_list $prop_entry
  968. }
  969. }
  970. }
  971. proc is_deprecated_property { property } {
  972. # Summary: filter old properties
  973. # Argument Usage:
  974. # Return Value:
  975. set property [string tolower $property]
  976. if { [string equal $property "runtime"] ||
  977. [string equal $property "unit_under_test"] ||
  978. [string equal $property "xelab.snapshot"] ||
  979. [string equal $property "xelab.debug_level"] ||
  980. [string equal $property "xelab.relax"] ||
  981. [string equal $property "xelab.mt_level"] ||
  982. [string equal $property "xelab.load_glbl"] ||
  983. [string equal $property "xelab.rangecheck"] ||
  984. [string equal $property "xelab.sdf_delay"] ||
  985. [string equal $property "xelab.unifast"] ||
  986. [string equal $property "xelab.nosort"] ||
  987. [string equal $property "xelab.more_options"] ||
  988. [string equal $property "xsim.view"] ||
  989. [string equal $property "xsim.wdb"] ||
  990. [string equal $property "xsim.saif"] ||
  991. [string equal $property "xsim.more_options"] ||
  992. [string equal $property "modelsim.custom_do"] ||
  993. [string equal $property "modelsim.custom_udo"] ||
  994. [string equal $property "modelsim.vhdl_syntax"] ||
  995. [string equal $property "modelsim.use_explicit_decl"] ||
  996. [string equal $property "modelsim.log_all_signals"] ||
  997. [string equal $property "modelsim.sdf_delay"] ||
  998. [string equal $property "modelsim.saif"] ||
  999. [string equal $property "modelsim.incremental"] ||
  1000. [string equal $property "modelsim.unifast"] ||
  1001. [string equal $property "modelsim.64bit"] ||
  1002. [string equal $property "modelsim.vsim_more_options"] ||
  1003. [string equal $property "modelsim.vlog_more_options"] ||
  1004. [string equal $property "modelsim.vcom_more_options"] } {
  1005. return true
  1006. }
  1007. return false
  1008. }
  1009. proc write_files { proj_dir proj_name tcl_obj type } {
  1010. # Summary: write file and file properties
  1011. # This helper command is used to script help.
  1012. # Argument Usage:
  1013. # Return Value:
  1014. # none
  1015. variable a_global_vars
  1016. variable l_script_data
  1017. set l_local_file_list [list]
  1018. set l_remote_file_list [list]
  1019. # return if empty fileset
  1020. if {[llength [get_files -quiet -of_objects [get_filesets $tcl_obj]]] == 0 } {
  1021. lappend l_script_data "# Empty (no sources present)\n"
  1022. return
  1023. }
  1024. set fs_name [get_filesets $tcl_obj]
  1025. set import_coln [list]
  1026. set add_file_coln [list]
  1027. foreach file [get_files -norecurse -of_objects [get_filesets $tcl_obj]] {
  1028. if { [file extension $file] == ".xcix" } { continue }
  1029. set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  1030. set begin [lsearch -exact $path_dirs "$proj_name.srcs"]
  1031. set src_file [join [lrange $path_dirs $begin+1 end] "/"]
  1032. # fetch first object
  1033. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
  1034. set file_props [list_property $file_object]
  1035. if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
  1036. # import files
  1037. set imported_path [get_property "imported_from" $file]
  1038. set rel_file_path [get_relative_file_path_for_source $file [get_script_execution_dir]]
  1039. set proj_file_path "\$origin_dir/$rel_file_path"
  1040. set file "\"[file normalize $proj_dir/${proj_name}.srcs/$src_file]\""
  1041. if { $a_global_vars(b_arg_no_copy_srcs) } {
  1042. # add to the local collection
  1043. lappend l_remote_file_list $file
  1044. if { $a_global_vars(b_absolute_path) } {
  1045. lappend add_file_coln "$file"
  1046. } else {
  1047. lappend add_file_coln "\"\[file normalize \"$proj_file_path\"\]\""
  1048. }
  1049. } else {
  1050. # add to the import collection
  1051. lappend l_local_file_list $file
  1052. if { $a_global_vars(b_absolute_path) } {
  1053. lappend import_coln "$file"
  1054. } else {
  1055. lappend import_coln "\"\[file normalize \"$proj_file_path\"\]\""
  1056. }
  1057. }
  1058. } else {
  1059. set file "\"$file\""
  1060. # is local? add to local project, add to collection and then import this collection by default unless -no_copy_sources is specified
  1061. if { [is_local_to_project $file] } {
  1062. if { $a_global_vars(b_arg_dump_proj_info) } {
  1063. set src_file "\$PSRCDIR/$src_file"
  1064. }
  1065. # add to the import collection
  1066. set file_no_quotes [string trim $file "\""]
  1067. set org_file_path "\$origin_dir/[get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]"
  1068. lappend import_coln "\"\[file normalize \"$org_file_path\"\]\""
  1069. lappend l_local_file_list $file
  1070. } else {
  1071. lappend l_remote_file_list $file
  1072. }
  1073. # add file to collection
  1074. if { $a_global_vars(b_arg_no_copy_srcs) && (!$a_global_vars(b_absolute_path))} {
  1075. set file_no_quotes [string trim $file "\""]
  1076. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  1077. set file1 "\"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
  1078. lappend add_file_coln "$file1"
  1079. } else {
  1080. lappend add_file_coln "$file"
  1081. }
  1082. # set flag that local sources were found and print warning at the end
  1083. if { !$a_global_vars(b_local_sources) } {
  1084. set a_global_vars(b_local_sources) 1
  1085. }
  1086. }
  1087. }
  1088. if {[llength $add_file_coln]>0} {
  1089. lappend l_script_data "set files \[list \\"
  1090. foreach file $add_file_coln {
  1091. if { $a_global_vars(b_absolute_path) } {
  1092. lappend l_script_data " $file\\"
  1093. } else {
  1094. if { $a_global_vars(b_arg_no_copy_srcs) } {
  1095. lappend l_script_data " $file\\"
  1096. } else {
  1097. set file_no_quotes [string trim $file "\""]
  1098. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  1099. lappend l_script_data " \"\[file normalize \"\$origin_dir/$rel_file_path\"\]\"\\"
  1100. }
  1101. }
  1102. }
  1103. lappend l_script_data "\]"
  1104. lappend l_script_data "add_files -norecurse -fileset \$obj \$files"
  1105. lappend l_script_data ""
  1106. }
  1107. # now import local files if -no_copy_sources is not specified
  1108. if { ! $a_global_vars(b_arg_no_copy_srcs)} {
  1109. if { [llength $import_coln] > 0 } {
  1110. lappend l_script_data "# Import local files from the original project"
  1111. lappend l_script_data "set files \[list \\"
  1112. foreach ifile $import_coln {
  1113. lappend l_script_data " $ifile\\"
  1114. }
  1115. lappend l_script_data "\]"
  1116. # is this a IP block fileset? if yes, import files into current source fileset
  1117. if { [is_ip_fileset $tcl_obj] } {
  1118. lappend l_script_data "set imported_files \[import_files -fileset [current_fileset -srcset] \$files\]"
  1119. } else {
  1120. lappend l_script_data "set imported_files \[import_files -fileset $tcl_obj \$files\]"
  1121. }
  1122. lappend l_script_data ""
  1123. }
  1124. }
  1125. # write fileset file properties for remote files (added sources)
  1126. write_fileset_file_properties $tcl_obj $fs_name $proj_dir $l_remote_file_list "remote"
  1127. # write fileset file properties for local files (imported sources)
  1128. write_fileset_file_properties $tcl_obj $fs_name $proj_dir $l_local_file_list "local"
  1129. }
  1130. proc write_constrs { proj_dir proj_name tcl_obj type } {
  1131. # Summary: write constrs fileset files and properties
  1132. # Argument Usage:
  1133. # Return Value:
  1134. # none
  1135. variable a_global_vars
  1136. variable l_script_data
  1137. set fs_name [get_filesets $tcl_obj]
  1138. # return if empty fileset
  1139. if {[llength [get_files -quiet -of_objects [get_filesets $tcl_obj]]] == 0 } {
  1140. lappend l_script_data "# Empty (no sources present)\n"
  1141. return
  1142. }
  1143. foreach file [get_files -norecurse -of_objects [get_filesets $tcl_obj]] {
  1144. lappend l_script_data "# Add/Import constrs file and set constrs file properties"
  1145. set constrs_file {}
  1146. set file_category {}
  1147. set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  1148. set begin [lsearch -exact $path_dirs "$proj_name.srcs"]
  1149. set src_file [join [lrange $path_dirs $begin+1 end] "/"]
  1150. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
  1151. set file_props [list_property $file_object]
  1152. # constrs sources imported?
  1153. if { [lsearch $file_props "IMPORTED_FROM"] != -1 } {
  1154. set imported_path [get_property "imported_from" $file]
  1155. set rel_file_path [get_relative_file_path_for_source $file [get_script_execution_dir]]
  1156. set proj_file_path "\$origin_dir/$rel_file_path"
  1157. set file "\"[file normalize $proj_dir/${proj_name}.srcs/$src_file]\""
  1158. # donot copy imported constrs in new project? set it as remote file in new project.
  1159. if { $a_global_vars(b_arg_no_copy_srcs) } {
  1160. set constrs_file $file
  1161. set file_category "remote"
  1162. if { $a_global_vars(b_absolute_path) } {
  1163. add_constrs_file "$file"
  1164. } else {
  1165. set str "\"\[file normalize \"$proj_file_path\"\]\""
  1166. add_constrs_file $str
  1167. }
  1168. } else {
  1169. # copy imported constrs in new project. Set it as local file in new project.
  1170. set constrs_file $file
  1171. set file_category "local"
  1172. if { $a_global_vars(b_absolute_path) } {
  1173. import_constrs_file $tcl_obj "$file"
  1174. } else {
  1175. set str "\"\[file normalize \"$proj_file_path\"\]\""
  1176. import_constrs_file $tcl_obj $str
  1177. }
  1178. }
  1179. } else {
  1180. # constrs sources were added, so check if these are local or added from remote location
  1181. set file "\"$file\""
  1182. set constrs_file $file
  1183. # is added constrs local to the project? import it in the new project and set it as local in the new project
  1184. if { [is_local_to_project $file] } {
  1185. # file is added from within project, so set it as local in the new project
  1186. set file_category "local"
  1187. if { $a_global_vars(b_arg_dump_proj_info) } {
  1188. set src_file "\$PSRCDIR/$src_file"
  1189. }
  1190. set file_no_quotes [string trim $file "\""]
  1191. set org_file_path "\$origin_dir/[get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]"
  1192. set str "\"\[file normalize \"$org_file_path\"\]\""
  1193. if { $a_global_vars(b_arg_no_copy_srcs)} {
  1194. add_constrs_file "$str"
  1195. } else {
  1196. import_constrs_file $tcl_obj $str
  1197. }
  1198. } else {
  1199. # file is added from remote location, so set it as remote in the new project
  1200. set file_category "remote"
  1201. # find relative file path of the added constrs if no_copy in the new project
  1202. if { $a_global_vars(b_arg_no_copy_srcs) && (!$a_global_vars(b_absolute_path))} {
  1203. set file_no_quotes [string trim $file "\""]
  1204. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  1205. set file_1 "\"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
  1206. add_constrs_file "$file_1"
  1207. } else {
  1208. add_constrs_file "$file"
  1209. }
  1210. }
  1211. # set flag that local sources were found and print warning at the end
  1212. if { !$a_global_vars(b_local_sources) } {
  1213. set a_global_vars(b_local_sources) 1
  1214. }
  1215. }
  1216. write_constrs_fileset_file_properties $tcl_obj $fs_name $proj_dir $constrs_file $file_category
  1217. }
  1218. }
  1219. proc add_constrs_file { file_str } {
  1220. # Summary: add constrs file
  1221. # This helper command is used to script help.
  1222. # Argument Usage:
  1223. # Return Value:
  1224. # none
  1225. variable a_global_vars
  1226. variable l_script_data
  1227. if { $a_global_vars(b_absolute_path) } {
  1228. lappend l_script_data "set file $file_str"
  1229. } else {
  1230. if { $a_global_vars(b_arg_no_copy_srcs) } {
  1231. lappend l_script_data "set file $file_str"
  1232. } else {
  1233. set file_no_quotes [string trim $file_str "\""]
  1234. set rel_file_path [get_relative_file_path_for_source $file_no_quotes [get_script_execution_dir]]
  1235. lappend l_script_data "set file \"\[file normalize \"\$origin_dir/$rel_file_path\"\]\""
  1236. }
  1237. }
  1238. lappend l_script_data "set file_added \[add_files -norecurse -fileset \$obj \$file\]"
  1239. }
  1240. proc import_constrs_file { tcl_obj file_str } {
  1241. # Summary: import constrs file
  1242. # This helper command is used to script help.
  1243. # Argument Usage:
  1244. # Return Value:
  1245. # none
  1246. variable a_global_vars
  1247. variable l_script_data
  1248. # now import local files if -no_copy_sources is not specified
  1249. if { ! $a_global_vars(b_arg_no_copy_srcs)} {
  1250. lappend l_script_data "set file $file_str"
  1251. lappend l_script_data "set file_imported \[import_files -fileset $tcl_obj \$file\]"
  1252. }
  1253. }
  1254. proc write_constrs_fileset_file_properties { tcl_obj fs_name proj_dir file file_category } {
  1255. # Summary: write constrs fileset file properties
  1256. # This helper command is used to script help.
  1257. # Argument Usage:
  1258. # Return Value:
  1259. # none
  1260. variable a_global_vars
  1261. variable l_script_data
  1262. variable l_local_files
  1263. variable l_remote_files
  1264. set file_prop_count 0
  1265. # collect local/remote files for the header section
  1266. if { [string equal $file_category "local"] } {
  1267. lappend l_local_files $file
  1268. } elseif { [string equal $file_category "remote"] } {
  1269. lappend l_remote_files $file
  1270. }
  1271. set file [string trim $file "\""]
  1272. # fix file path for local files
  1273. if { [string equal $file_category "local"] } {
  1274. set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  1275. set src_file [join [lrange $path_dirs end-1 end] "/"]
  1276. set src_file [string trimleft $src_file "/"]
  1277. set src_file [string trimleft $src_file "\\"]
  1278. set file $src_file
  1279. }
  1280. set file_object ""
  1281. if { [string equal $file_category "local"] } {
  1282. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list "*$file"]] 0]
  1283. } elseif { [string equal $file_category "remote"] } {
  1284. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
  1285. }
  1286. # get the constrs file properties
  1287. set file_props [list_property $file_object]
  1288. set prop_info_list [list]
  1289. set prop_count 0
  1290. foreach file_prop $file_props {
  1291. set is_readonly [get_property is_readonly [rdi::get_attr_specs $file_prop -object $file_object]]
  1292. if { [string equal $is_readonly "1"] } {
  1293. continue
  1294. }
  1295. set prop_type [get_property type [rdi::get_attr_specs $file_prop -object $file_object]]
  1296. set def_val [list_property_value -default $file_prop $file_object]
  1297. set cur_val [get_property $file_prop $file_object]
  1298. # filter special properties
  1299. if { [filter $file_prop $cur_val $file] } { continue }
  1300. # re-align values
  1301. set cur_val [get_target_bool_val $def_val $cur_val]
  1302. set dump_prop_name [string tolower ${fs_name}_file_${file_prop}]
  1303. set prop_entry ""
  1304. if { [string equal $file_category "local"] } {
  1305. set prop_entry "[string tolower $file_prop]#[get_property $file_prop $file_object]"
  1306. } elseif { [string equal $file_category "remote"] } {
  1307. set prop_value_entry [get_property $file_prop $file_object]
  1308. set prop_entry "[string tolower $file_prop]#$prop_value_entry"
  1309. }
  1310. # include all properties?
  1311. if { $a_global_vars(b_arg_all_props) } {
  1312. lappend prop_info_list $prop_entry
  1313. incr prop_count
  1314. } else {
  1315. # include only non-default (default behavior)
  1316. if { $def_val != $cur_val } {
  1317. lappend prop_info_list $prop_entry
  1318. incr prop_count
  1319. }
  1320. }
  1321. if { $a_global_vars(b_arg_dump_proj_info) } {
  1322. puts $a_global_vars(def_val_fh) "[file tail $file]=$file_prop ($prop_type) :DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
  1323. puts $a_global_vars(dp_fh) "$dump_prop_name=$cur_val"
  1324. }
  1325. }
  1326. # write properties now
  1327. if { $prop_count>0 } {
  1328. if { {remote} == $file_category } {
  1329. if { $a_global_vars(b_absolute_path) } {
  1330. lappend l_script_data "set file \"$file\""
  1331. } else {
  1332. lappend l_script_data "set file \"\$origin_dir/[get_relative_file_path_for_source $file [get_script_execution_dir]]\""
  1333. lappend l_script_data "set file \[file normalize \$file\]"
  1334. }
  1335. } else {
  1336. lappend l_script_data "set file \"$file\""
  1337. }
  1338. lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets $tcl_obj\] \[list \"*\$file\"\]\]"
  1339. set get_what "get_files"
  1340. write_properties $prop_info_list $get_what $tcl_obj
  1341. incr file_prop_count
  1342. }
  1343. if { $file_prop_count == 0 } {
  1344. lappend l_script_data "# None"
  1345. }
  1346. }
  1347. proc write_specified_run { proj_dir proj_name runs } {
  1348. # Summary: write the specified run information
  1349. # This helper command is used to script help.
  1350. # Argument Usage:
  1351. # Return Value:
  1352. # none
  1353. variable a_global_vars
  1354. variable l_script_data
  1355. set get_what "get_runs"
  1356. foreach tcl_obj $runs {
  1357. # is block fileset based run that contains IP? donot create OOC run
  1358. if { [is_ip_run $tcl_obj] } {
  1359. continue
  1360. }
  1361. # fetch run attributes
  1362. set part [get_property part [$get_what $tcl_obj]]
  1363. set parent_run [get_property parent [$get_what $tcl_obj]]
  1364. set src_set [get_property srcset [$get_what $tcl_obj]]
  1365. set constrs_set [get_property constrset [$get_what $tcl_obj]]
  1366. set strategy [get_property strategy [$get_what $tcl_obj]]
  1367. set parent_run_str ""
  1368. if { $parent_run != "" } {
  1369. set parent_run_str " -parent_run $parent_run"
  1370. }
  1371. set def_flow_type_val [list_property_value -default flow [$get_what $tcl_obj]]
  1372. set cur_flow_type_val [get_property flow [$get_what $tcl_obj]]
  1373. set def_strat_type_val [list_property_value -default strategy [$get_what $tcl_obj]]
  1374. set cur_strat_type_val [get_property strategy [$get_what $tcl_obj]]
  1375. lappend l_script_data "# Create '$tcl_obj' run (if not found)"
  1376. lappend l_script_data "if \{\[string equal \[get_runs -quiet $tcl_obj\] \"\"\]\} \{"
  1377. set cmd_str " create_run -name $tcl_obj -part $part -flow {$cur_flow_type_val} -strategy \"$cur_strat_type_val\""
  1378. lappend l_script_data "$cmd_str -constrset $constrs_set$parent_run_str"
  1379. lappend l_script_data "\} else \{"
  1380. lappend l_script_data " set_property strategy \"$cur_strat_type_val\" \[get_runs $tcl_obj\]"
  1381. lappend l_script_data " set_property flow \"$cur_flow_type_val\" \[get_runs $tcl_obj\]"
  1382. lappend l_script_data "\}"
  1383. lappend l_script_data "set obj \[$get_what $tcl_obj\]"
  1384. write_props $proj_dir $proj_name $get_what $tcl_obj "run"
  1385. }
  1386. }
  1387. proc get_fileset_type_switch { fileset_type } {
  1388. # Summary: Return the fileset type switch for a given fileset
  1389. # Argument Usage:
  1390. # Return Value:
  1391. # Fileset type switch name
  1392. variable a_fileset_types
  1393. set fs_switch ""
  1394. foreach {fs_data} $a_fileset_types {
  1395. set fs_type [lindex $fs_data 0]
  1396. if { [string equal -nocase $fileset_type $fs_type] } {
  1397. set fs_switch [lindex $fs_data 1]
  1398. set fs_switch "-$fs_switch"
  1399. break
  1400. }
  1401. }
  1402. return $fs_switch
  1403. }
  1404. proc get_target_bool_val { def_val cur_val } {
  1405. # Summary: Resolve current boolean property value wrt its default value
  1406. # Argument Usage:
  1407. # Return Value:
  1408. # Resolved boolean value
  1409. set target_val $cur_val
  1410. if { [string equal $def_val "false"] && [string equal $cur_val "0"] } { set target_val "false" } \
  1411. elseif { [string equal $def_val "true"] && [string equal $cur_val "1"] } { set target_val "true" } \
  1412. elseif { [string equal $def_val "false"] && [string equal $cur_val "1"] } { set target_val "true" } \
  1413. elseif { [string equal $def_val "true"] && [string equal $cur_val "0"] } { set target_val "false" } \
  1414. elseif { [string equal $def_val "{}"] && [string equal $cur_val ""] } { set target_val "{}" }
  1415. return $target_val
  1416. }
  1417. proc write_fileset_file_properties { tcl_obj fs_name proj_dir l_file_list file_category } {
  1418. # Summary:
  1419. # Write fileset file properties for local and remote files
  1420. # Argument Usage:
  1421. # tcl_obj: object to inspect
  1422. # fs_name: fileset name
  1423. # l_file_list: list of files (local or remote)
  1424. # file_category: file catwgory (local or remote)
  1425. # Return Value:
  1426. # none
  1427. variable a_global_vars
  1428. variable l_script_data
  1429. variable l_local_files
  1430. variable l_remote_files
  1431. # is this a IP block fileset? if yes, set current source fileset
  1432. if { [is_ip_fileset $tcl_obj] } {
  1433. lappend l_script_data "# Set '[current_fileset -srcset]' fileset file properties for $file_category files"
  1434. } else {
  1435. lappend l_script_data "# Set '$tcl_obj' fileset file properties for $file_category files"
  1436. }
  1437. set file_prop_count 0
  1438. # collect local/remote files
  1439. foreach file $l_file_list {
  1440. if { [string equal $file_category "local"] } {
  1441. lappend l_local_files $file
  1442. } elseif { [string equal $file_category "remote"] } {
  1443. lappend l_remote_files $file
  1444. } else {}
  1445. }
  1446. foreach file $l_file_list {
  1447. set file [string trim $file "\""]
  1448. # fix file path for local files
  1449. if { [string equal $file_category "local"] } {
  1450. set path_dirs [split [string trim [file normalize [string map {\\ /} $file]]] "/"]
  1451. set src_file [join [lrange $path_dirs end-1 end] "/"]
  1452. set src_file [string trimleft $src_file "/"]
  1453. set src_file [string trimleft $src_file "\\"]
  1454. set file $src_file
  1455. }
  1456. set file_object ""
  1457. if { [string equal $file_category "local"] } {
  1458. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list "*$file"]] 0]
  1459. } elseif { [string equal $file_category "remote"] } {
  1460. set file_object [lindex [get_files -of_objects [get_filesets $fs_name] [list $file]] 0]
  1461. }
  1462. set file_props [list_property $file_object]
  1463. set prop_info_list [list]
  1464. set prop_count 0
  1465. foreach file_prop $file_props {
  1466. set is_readonly [get_property is_readonly [rdi::get_attr_specs $file_prop -object $file_object]]
  1467. if { [string equal $is_readonly "1"] } {
  1468. continue
  1469. }
  1470. set prop_type [get_property type [rdi::get_attr_specs $file_prop -object $file_object]]
  1471. set def_val [list_property_value -default $file_prop $file_object]
  1472. set cur_val [get_property $file_prop $file_object]
  1473. # filter special properties
  1474. if { [filter $file_prop $cur_val $file] } { continue }
  1475. # re-align values
  1476. set cur_val [get_target_bool_val $def_val $cur_val]
  1477. set dump_prop_name [string tolower ${fs_name}_file_${file_prop}]
  1478. set prop_entry ""
  1479. if { [string equal $file_category "local"] } {
  1480. set prop_entry "[string tolower $file_prop]#[get_property $file_prop $file_object]"
  1481. } elseif { [string equal $file_category "remote"] } {
  1482. set prop_value_entry [get_property $file_prop $file_object]
  1483. set prop_entry "[string tolower $file_prop]#$prop_value_entry"
  1484. } else {}
  1485. if { $a_global_vars(b_arg_all_props) } {
  1486. lappend prop_info_list $prop_entry
  1487. incr prop_count
  1488. } else {
  1489. if { $def_val != $cur_val } {
  1490. lappend prop_info_list $prop_entry
  1491. incr prop_count
  1492. }
  1493. }
  1494. if { $a_global_vars(b_arg_dump_proj_info) } {
  1495. puts $a_global_vars(def_val_fh) "[file tail $file]=$file_prop ($prop_type) :DEFAULT_VALUE ($def_val)==CURRENT_VALUE ($cur_val)"
  1496. puts $a_global_vars(dp_fh) "$dump_prop_name=$cur_val"
  1497. }
  1498. }
  1499. # write properties now
  1500. if { $prop_count>0 } {
  1501. if { {remote} == $file_category } {
  1502. if { $a_global_vars(b_absolute_path) } {
  1503. lappend l_script_data "set file \"$file\""
  1504. } else {
  1505. lappend l_script_data "set file \"\$origin_dir/[get_relative_file_path_for_source $file [get_script_execution_dir]]\""
  1506. lappend l_script_data "set file \[file normalize \$file\]"
  1507. }
  1508. } else {
  1509. lappend l_script_data "set file \"$file\""
  1510. }
  1511. # is this a IP block fileset? if yes, get files from current source fileset
  1512. if { [is_ip_fileset $tcl_obj] } {
  1513. lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets [current_fileset -srcset]\] \[list \"*\$file\"\]\]"
  1514. } else {
  1515. lappend l_script_data "set file_obj \[get_files -of_objects \[get_filesets $tcl_obj\] \[list \"*\$file\"\]\]"
  1516. }
  1517. set get_what "get_files"
  1518. write_properties $prop_info_list $get_what $tcl_obj
  1519. incr file_prop_count
  1520. }
  1521. }
  1522. if { $file_prop_count == 0 } {
  1523. lappend l_script_data "# None"
  1524. }
  1525. lappend l_script_data ""
  1526. }
  1527. proc get_script_execution_dir { } {
  1528. # Summary: Return script directory path from where the script will be executed
  1529. # Argument Usage:
  1530. # none
  1531. # Return Value:
  1532. # Path to the script direc
  1533. variable a_global_vars
  1534. # default: return script directory path
  1535. set scr_exe_dir $a_global_vars(s_path_to_script_dir)
  1536. # is -path_to_relative specified and the path exists? return this dir
  1537. set rel_to_dir $a_global_vars(s_relative_to)
  1538. if { ("." != $rel_to_dir) } {
  1539. set rel_to_dir [file normalize $rel_to_dir]
  1540. if { [file exists $rel_to_dir] } {
  1541. set scr_exe_dir $rel_to_dir
  1542. }
  1543. }
  1544. return $scr_exe_dir
  1545. }
  1546. # TODO: This is the same as xcs_get_relative_file_path for simulators, see common/utils.tcl
  1547. # Remember to add the 'source .../common/utils.tcl' in the write_project_tcl proc to load the common file
  1548. proc get_relative_file_path_for_source { file_path_to_convert relative_to } {
  1549. # Summary: Get the relative path wrt to path specified
  1550. # Argument Usage:
  1551. # file_path_to_convert: input file to make relative to specfied path
  1552. # Return Value:
  1553. # Relative path wrt the path specified
  1554. variable a_xport_sim_vars
  1555. # make sure we are dealing with a valid relative_to directory. If regular file or is not a directory, get directory
  1556. if { [file isfile $relative_to] || ![file isdirectory $relative_to] } {
  1557. set relative_to [file dirname $relative_to]
  1558. }
  1559. set cwd [file normalize [pwd]]
  1560. if { [file pathtype $file_path_to_convert] eq "relative" } {
  1561. # is relative_to path same as cwd?, just return this path, no further processing required
  1562. if { [string equal $relative_to $cwd] } {
  1563. return $file_path_to_convert
  1564. }
  1565. # the specified path is "relative" but something else, so make it absolute wrt current working dir
  1566. set file_path_to_convert [file join $cwd $file_path_to_convert]
  1567. }
  1568. # is relative_to "relative"? convert to absolute as well wrt cwd
  1569. if { [file pathtype $relative_to] eq "relative" } {
  1570. set relative_to [file join $cwd $relative_to]
  1571. }
  1572. # normalize
  1573. set file_path_to_convert [file normalize $file_path_to_convert]
  1574. set relative_to [file normalize $relative_to]
  1575. set file_path $file_path_to_convert
  1576. set file_comps [file split $file_path]
  1577. set relative_to_comps [file split $relative_to]
  1578. set found_match false
  1579. set index 0
  1580. set fc_comps_len [llength $file_comps]
  1581. set rt_comps_len [llength $relative_to_comps]
  1582. # compare each dir element of file_to_convert and relative_to, set the flag and
  1583. # get the final index till these sub-dirs matched. Break if limit reaches.
  1584. while { [lindex $file_comps $index] == [lindex $relative_to_comps $index] } {
  1585. if { !$found_match } { set found_match true }
  1586. incr index
  1587. if { ($index == $fc_comps_len) || ($index == $rt_comps_len) } {
  1588. break;
  1589. }
  1590. }
  1591. # any common dirs found? convert path to relative
  1592. if { $found_match } {
  1593. set parent_dir_path ""
  1594. set rel_index $index
  1595. # keep traversing the relative_to dirs and build "../" levels
  1596. while { [lindex $relative_to_comps $rel_index] != "" } {
  1597. set parent_dir_path "../$parent_dir_path"
  1598. incr rel_index
  1599. }
  1600. #
  1601. # at this point we have parent_dir_path setup with exact number of sub-dirs to go up
  1602. #
  1603. # now build up part of path which is relative to matched part
  1604. set rel_path ""
  1605. set rel_index $index
  1606. while { [lindex $file_comps $rel_index] != "" } {
  1607. set comps [lindex $file_comps $rel_index]
  1608. if { $rel_path == "" } {
  1609. # first dir
  1610. set rel_path $comps
  1611. } else {
  1612. # append remaining dirs
  1613. set rel_path "${rel_path}/$comps"
  1614. }
  1615. incr rel_index
  1616. }
  1617. # prepend parent dirs, this is the complete resolved path now
  1618. set resolved_path "${parent_dir_path}${rel_path}"
  1619. return $resolved_path
  1620. }
  1621. # no common dirs found, just return the normalized path
  1622. return $file_path
  1623. }
  1624. proc is_ip_fileset { fileset } {
  1625. # Summary: Find IP's if any from the specified fileset and return true if 'generate_synth_checkpoint' is set to 1
  1626. # Argument Usage:
  1627. # fileset: fileset name
  1628. # Return Value:
  1629. # true (1) if success, false (0) otherwise
  1630. # make sure fileset is block fileset type
  1631. if { {BlockSrcs} != [get_property fileset_type [get_filesets $fileset]] } {
  1632. return false
  1633. }
  1634. set ip_filter "FILE_TYPE == \"IP\" || FILE_TYPE==\"Block Designs\""
  1635. set ips [get_files -all -quiet -of_objects [get_filesets $fileset] -filter $ip_filter]
  1636. set b_found false
  1637. foreach ip $ips {
  1638. if { [get_property generate_synth_checkpoint [lindex [get_files -all $ip] 0]] } {
  1639. set b_found true
  1640. break
  1641. }
  1642. }
  1643. if { $b_found } {
  1644. return true
  1645. }
  1646. return false
  1647. }
  1648. proc is_proxy_ip_fileset { fileset } {
  1649. # Summary: Determine if the fileset is an OOC run for a proxy IP that has a parent composite
  1650. # Argument Usage:
  1651. # fileset: fileset name
  1652. # Return Value:
  1653. # true (1) if the fileset contains an IP at its root with a parent composite, false (0) otherwise
  1654. # make sure fileset is block fileset type
  1655. if { {BlockSrcs} != [get_property fileset_type [get_filesets $fileset]] } {
  1656. return false
  1657. }
  1658. set ip_with_parent_filter "FILE_TYPE == IP && PARENT_COMPOSITE_FILE != \"\""
  1659. if {[llength [get_files -norecurse -quiet -of_objects [get_filesets $fileset] -filter $ip_with_parent_filter]] == 1} {
  1660. return true
  1661. }
  1662. return false
  1663. }
  1664. proc is_ip_run { run } {
  1665. # Summary: Find IP's if any from the fileset linked with the block fileset run
  1666. # Argument Usage:
  1667. # run: run name
  1668. # Return Value:
  1669. # true (1) if success, false (0) otherwise
  1670. set fileset [get_property srcset [get_runs $run]]
  1671. return [is_ip_fileset $fileset]
  1672. }
  1673. }