Hog v10.38.0
launch.tcl
Go to the documentation of this file.
1 #!/usr/bin/env tclsh
2 # tcl-lsp: disable=W300
3 
4 # @file
5 # Copyright 2018-2026 The University of Birmingham
6 # Copyright 2018-2026 Max-Planck-Institute for Physics
7 #
8 # Licensed under the Apache License, Version 2.0 (the "License");
9 # you may not use this file except in compliance with the License.
10 # You may obtain a copy of the License at
11 #
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14 # Unless required by applicable law or agreed to in writing, software
15 # distributed under the License is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19 # Launch Xilinx Vivado or ISE implementation and possibly write bitstream in text mode
20 # Developers Tip for new commands
21 # Add a hashtag sign # after the curly brake (e.g. \^C(REATE)?$ {# ...}) if the command requires a project name as an argument
22 set tcl_path [file normalize "[file dirname [info script]]"]
23 source $tcl_path/hog.tcl
24 source $tcl_path/create_project.tcl
25 source $tcl_path/commands.tcl
26 
27 # Initialize Vitis flags before InitLauncher so IsTclsh correctly returns 1
28 set globalSettings::vitis_unified 0
29 set globalSettings::vitis_classic 0
30 
31 # Check if we're already running in xsct (Vitis Classic)
32 # This must be done early, before InitLauncher, to prevent launching Vivado
33 if {[info commands platform] ne ""} {
34  set globalSettings::vitis_classic 1
35  set globalSettings::vitis_unified 0
36 }
37 
38 # Quartus needs extra packages and treats the argv in a different way
39 if {[IsQuartus]} {
40  load_package report
41  # noqa: W210
42  set argv $quartus(args)
43 }
44 
45 
46 # Msg Debug "s: $::argv0 a: $argv"
47 ### CUSTOM COMMANDS ###
48 set commands_path [file normalize "$tcl_path/../../hog-commands/"]
49 set custom_commands [GetCustomCommands $parameters $commands_path]
50 
51 lassign [InitLauncher $::argv0 $tcl_path $parameters $default_commands $argv $custom_commands] directive project \
52  project_name group_name repo_path old_path bin_dir top_path usage short_usage cmd ide list_of_options
53 
54 array set options $list_of_options
55 
56 if {$options(verbose) == 1} {
57  setDebugMode 1
58 }
59 Msg Debug \
60  "Returned by InitLauncher: \n - project: $project \n - project_name $project_name \n - group_name $group_name \n - \
61  repo_path $repo_path \n - old_path $old_path \n - bin_dir $bin_dir \n - top_path $top_path \n - cmd $cmd"
62 
63 set ext_path ""
64 if {$options(ext_path) ne ""} {
65  set ext_path $options(ext_path)
66 }
67 set lib_path ""
68 if {$options(lib) ne ""} {
69  set lib_path [file normalize $options(lib)]
70 } else {
71  if {[info exists env(HOG_SIMULATION_LIB_PATH)]} {
72  set lib_path $env(HOG_SIMULATION_LIB_PATH)
73  } else {
74  if {[file exists "$repo_path/SimulationLib"]} {
75  set lib_path [file normalize "$repo_path/SimulationLib"]
76  } else {
77  set lib_path ""
78  }
79  }
80 }
81 
82 
83 if {$options(verbose) == 1} {
84  setDebugMode 1
85  # Set environment variable for Vitis Unified Python scripts to enable debug output
86  set env(HOG_DEBUG_MODE) "1"
87 }
88 
89 # printDebugMode
90 # Msg Info "Number of jobs set to $options(njobs)."
91 set output_path ""
92 if {$options(output) ne ""} {
93  set output_path $options(output)
94 }
95 
96 set light_hierarchy $options(light)
97 set ignored_hierarchy $options(ignore)
98 set top_module $options(top)
99 set compile_order $options(compile_order)
100 set include_ieee $options(include_ieee)
101 set include_gen_prods $options(include_gen_prods)
102 
103 ######## DEFAULTS #########
104 set do_rtl 0
105 set do_checkproj_env 0
106 set do_check_ci_env 0
107 set do_checkproj_ver 0
108 set do_implementation 0
109 set do_synthesis 0
110 set do_bitstream 0
111 set do_create 0
112 set do_compile 0
113 set do_simulation 0
114 set recreate 0
115 set do_reset 1
116 set do_list_all 2
117 set do_check_syntax 0
118 set do_vitis_build 0
119 set scripts_only 0
120 set compile_only 0
121 set ide_name ""
122 set allow_empty_proj 0
123 
124 ### Hog stand-alone directives ###
125 # The following directives are used WITHOUT ever calling the IDE, they are run in tclsh
126 # A place holder called new_directive can be followed to add new commands
127 set do_ipbus_xml 0
128 set do_list_file_parse 0
129 set do_check_yaml_ref 0
130 set do_buttons 0
131 set do_check_list_files 0
132 set do_compile_lib 0
133 set do_sigasi 0
134 set do_vhdl_ls 0
135 set do_cocotb 0
136 set do_hierarchy 0
137 set do_version 0
138 
139 set NO_DIRECTIVE_FOUND 0
140 Msg Debug "Looking for a $directive in : $default_commands"
141 switch -regexp -- $directive $default_commands
142 
143 if {$NO_DIRECTIVE_FOUND == 1} {
144  Msg Debug "No directive found in default commands, looking in custom commands..."
145  if {[string length $custom_commands] > 0 && [dict exists $custom_commands $directive]} {
146  Msg Debug "Directive $directive found in custom commands."
147  if {$cmd == "custom_tcl"} {
148  eval [dict get $custom_commands $directive SCRIPT]
149  exit
150  } else {
151  if {[IsTclsh]} {
152  Msg Info "Launching command: $cmd..."
153 
154  # Check if the IDE is actually in the path...
155  set ret [catch {exec which $ide}]
156  if {$ret != 0} {
157  Msg Error "$ide not found in your system. Make sure to add $ide to your PATH enviromental variable."
158  exit $ret
159  }
160 
161  if {[string first libero $cmd] >= 0} {
162  # The SCRIPT_ARGS: flag of libero makes tcl crazy...
163  # Let's pipe the command into a shell script and remove it later
164  set libero_script [open "launch-libero-hog.sh" w]
165  puts $libero_script "#!/bin/sh"
166  puts $libero_script $cmd
167  close $libero_script
168  set cmd "sh launch-libero-hog.sh"
169  }
170 
171  set ret [catch {exec -ignorestderr {*}$cmd >@ stdout 2>@ stderr} result]
172 
173  if {$ret != 0} {
174  Msg Error "IDE returned an error state."
175  } else {
176  Msg Info "All done."
177  exit 0
178  }
179 
180  if {[string first libero $cmd] >= 0} {
181  file delete "launch-libero-hog.sh"
182  }
183 
184  exit $ret
185  }
186 
187  eval [dict get $custom_commands $directive SCRIPT]
188 
189  set no_exit [dict get $custom_commands $directive NO_EXIT]
190  if {$no_exit == 0} {
191  exit
192  }
193  }
194  } else {
195  Msg Info "No directive found, pre ide exiting..."
196  Msg Status "ERROR: Unknown directive $directive.\n\n"
197  puts $usage
198  exit
199  }
200 }
201 
202 if {$options(all) == 1} {
203  set do_list_all 1
204 } else {
205  set do_list_all 2
206 }
207 
208 set ci_run 0
209 if {$options(ci_run) == 1} {
210  set ci_run 1
211 }
212 
213 if {$options(dst_dir) == "" && ($do_ipbus_xml == 1 || $do_check_list_files == 1) && $project != ""} {
214  # Getting all the versions and SHAs of the repository
215  lassign [GetRepoVersions [file normalize $repo_path/Top/$group_name/$project] $repo_path $ext_path] commit version \
216  hog_hash hog_ver top_hash top_ver libs hashes vers cons_ver cons_hash ext_names ext_hashes xml_hash xml_ver \
217  user_ip_repos user_ip_hashes user_ip_vers
218  cd $repo_path
219 
220  set describe [GetHogDescribe [file normalize $repo_path/Top/$group_name/$project] $repo_path]
221  set dst_dir [file normalize "$repo_path/bin/$group_name/$project\-$describe"]
222 }
223 
224 if {$cmd == -1} {
225  # This is if the project was not found
226  Msg Status "\n\nPossible projects are:"
227  ListProjects $repo_path $do_list_all
228  Msg Status "\n"
229  exit 1
230 } elseif {$cmd == -2} {
231  # Project not given but needed
232  Msg Status "ERROR: You must specify a project with directive $directive."
233  # \n\n[cmdline::usage $parameters $usage]"
234  Msg Status "Possible projects are:"
235  ListProjects $repo_path $do_list_all
236  exit 1
237 } elseif {$cmd == 0} {
238  #This script was launched within the IDE,: Vivado, Quartus, etc
239  Msg Info "$::argv0 was launched from the IDE."
240 } else {
241  # This script was launched with Tclsh, we need to check the arguments
242  # and if everything is right launch the IDE on this script and return
243  #### Directives to be handled in tclsh should be here ###
244  ### IMPORTANT: Each if block should either end with "exit 0" or
245  ### set both $ide and $cmd to be executed when this script is run again
246  if {$do_checkproj_env == 1} {
247  CheckEnv $project_name $ide
248  exit 0
249  }
250 
251  if {$do_checkproj_ver == 1} {
252  cd $repo_path
253  set ci_config ""
254  if {$ci_run == 1} {
255  # Compile YAML to get list of projects
256  if {[info exists env(GITLAB_CI)] && $env(GITLAB_CI) eq "true" && [auto_execok glab] != ""} {
257  # running in GitLab CI
258  Msg Info "Running in the GitLab CI/CD. I will check only the active projects in the current pipeline..."
259  # Tell glab the host and project explicitly: on SaaS runners the git remote
260  # points to the CI gateway, which glab does not recognise as a GitLab host.
261  if {[info exists env(CI_SERVER_HOST)]} {
262  set env(GITLAB_HOST) $env(CI_SERVER_HOST)
263  }
264  if {[info exists env(CI_PROJECT_PATH)]} {
265  lassign [ExecuteRet glab ci get -p $env(CI_PIPELINE_ID)] ret ci_config
266  } else {
267  lassign [ExecuteRet glab ci get] ret ci_config
268  }
269  if {$ret != 0} {
270  Msg Warning "Failed to get CI config from GitLab, checking all projects instead."
271  set ci_run 0
272  }
273 
274  # Check if we are using the dynamic CI and set ci_run to 0 in case, so we check the version of all projects
275  if {[info exists env(CI_CONFIG_PATH)]} {
276  set ci_config_path $env(CI_CONFIG_PATH)
277  } else {
278  set ci_config_path $repo_path/.gitlab-ci.yml
279  }
280 
281  if {[file exists $ci_config_path]} {
282  set fh [open $ci_config_path r]
283  set content [read $fh]
284  close $fh
285  if {[string first "hog-dynamic.yml" $content] != -1} {
286  set ci_run 0
287  }
288  } else {
289  Msg Warning "CI config file $ci_config_path not found, checking all projects instead."
290  set ci_run 0
291  }
292  } elseif {[info exists env(GITHUB_ACTIONS)] && $env(GITHUB_ACTIONS) eq "true"} {
293  # running in GitHub Actions
294  set workflow_dir "$repo_path/.github/workflows"
295  set ci_run 0
296  foreach workflow_file [glob -nocomplain -directory $workflow_dir -- *.yml *.yaml] {
297  set fh [open $workflow_file r]
298  set content [read $fh]
299  close $fh
300  if {[string first "Hog-pull.yml" $content] != -1} {
301  set ci_config $content
302  set ci_run 1
303  break
304  }
305  }
306  } else {
307  set ci_run 0
308  }
309  }
310 
311  set proj_to_do {}
312  if {$project_name eq ""} {
313  set projects [ListProjects $repo_path 1 0 1]
314  foreach p $projects {
315  if {$ci_run == 0 || ($ci_run == 1 && [string first $p $ci_config] != -1)} {
316  if {[CheckProjVer $repo_path $p $options(simcheck) $options(ext_path)] == 0} {
317  lappend proj_to_do $p
318  }
319  }
320  }
321  } else {
322  if {[CheckProjVer $repo_path $project_name $options(simcheck) $options(ext_path)] == 0} {
323  lappend proj_to_do $project_name
324  }
325  }
326 
327  set n [llength $proj_to_do]
328  if {$n > 0} {
329  Msg Info "The following projects were modified: \n[join $proj_to_do \n]"
330  }
331 
332  Msg Info "$n projects were modified since last official version."
333  exit 0
334  }
335 
336  if {$do_check_ci_env == 1} {
337  CheckCIEnv
338  exit 0
339  }
340 
341 
342  if {$do_ipbus_xml == 1} {
343  if {[llength $project_name] == 0} {
344  Msg Error "XML option needs a project name."
345  exit
346  }
347  Msg Info "Handling IPbus XMLs for $project_name..."
348 
349  set proj_dir $repo_path/Top/$project_name
350 
351  if {$options(generate) == 1} {
352  set xml_gen 1
353  } else {
354  set xml_gen 0
355  }
356 
357  if {$options(dst_dir) != ""} {
358  set dst_dir $options(dst_dir)
359  } else {
360  if {![info exists dst_dir]} {
361  set dst_dir ""
362  }
363  }
364  set xml_dst "$dst_dir/xml"
365 
366 
367  if {[llength [glob -nocomplain $proj_dir/list/*.ipb]] > 0} {
368  if {![file exists $xml_dst]} {
369  Msg Info "$xml_dst directory not found, creating it..."
370  file mkdir $xml_dst
371  }
372  } else {
373  Msg Error "No .ipb files found in $proj_dir/list/"
374  exit
375  }
376 
377  set ret [GetRepoVersions $proj_dir $repo_path ""]
378  set sha [lindex $ret 13]
379  set hex_ver [lindex $ret 14]
380 
381  set ver [HexVersionToString $hex_ver]
382  CopyIPbusXMLs $proj_dir $repo_path $xml_dst $ver $sha 1 $xml_gen
383 
384  exit 0
385  }
386 
387  if {$do_list_file_parse == 1} {
388  set proj_dir $repo_path/Top/$project_name
389  set proj_list_dir $repo_path/Top/$project_name/list
390  GetHogFiles -print_log -list_files {.src,.con,.sim,.ext,.ipb} $proj_list_dir $repo_path
391  Msg Status " "
392  Msg Info "All Done."
393  exit 0
394  }
395 
396  if {$do_hierarchy == 1} {
397  source $tcl_path/utils/hierarchy.tcl
398  set proj_dir $repo_path/Top/$project_name
399  set proj_list_dir $repo_path/Top/$project_name/list
400  lassign [GetHogFiles -ext_path $ext_path -list_files ".src,.ext" $proj_list_dir $repo_path] listLibraries \
401  listProperties listSrcSets
402  set hierarchy_result \
403  [Hierarchy $listProperties $listLibraries $repo_path $output_path $compile_order $light_hierarchy $top_module \
404  $ignored_hierarchy $include_ieee $include_gen_prods]
405  puts $hierarchy_result
406  exit 0
407  }
408  if {$do_sigasi == 1} {
409  cd $repo_path
410  Msg Info "Creating Sigasi CSV files for project $project_name..."
411  set proj_dir $repo_path/Top/$project_name
412  set proj_list_dir $repo_path/Top/$project_name/list
413  set project [file tail $project_name]
414  lassign [GetHogFiles -list_files {.src} $proj_list_dir $repo_path] libraries
415  set csv_file [open "sigasi_$project.csv" w]
416  foreach lib $libraries {
417  set source_files [DictGet $libraries $lib]
418  foreach source_file $source_files {
419  if {
420  [file extension $source_file] eq ".vhd"
421  || [file extension $source_file] eq ".vhdl"
422  || [file extension $source_file] eq ".sv"
423  || [file extension $source_file] eq ".v"
424  } {
425  puts $csv_file [concat [file rootname $lib] "," $source_file]
426  }
427  }
428  }
429  lassign [GetHogFiles -list_files ".sim" $proj_list_dir $repo_path] \
430  listSimLibraries
431  foreach lib $listSimLibraries {
432  set source_files [DictGet $listSimLibraries $lib]
433  foreach source_file $source_files {
434  if {
435  [file extension $source_file] eq ".vhd"
436  || [file extension $source_file] eq ".vhdl"
437  || [file extension $source_file] eq ".sv"
438  || [file extension $source_file] eq ".v"
439  } {
440  puts $csv_file [concat [file rootname $lib] "," $source_file]
441  }
442  }
443  }
444  close $csv_file
445  Msg Info "Sigasi CSV file created: sigasi_$project.csv"
446  Msg Info "You can use the python script provided by Sigasi to convert the generated csv file into a Sigasi project."
447  Msg Info \
448  "More info at: \
449  https://www.sigasi.com/knowledge/how_tos/generating-sigasi-project-vivado-project/#2-generate-the-sigasi-project-files-from-the-csv-file"
450  exit 0
451  }
452 
453  if {$do_vhdl_ls == 1} {
454  cd $repo_path
455  Msg Info "Creating VHDL-LS configuration file for project $project_name..."
456  set proj_dir $repo_path/Top/$project_name
457  set proj_list_dir $repo_path/Top/$project_name/list
458  set project [file tail $project_name]
459  lassign [GetHogFiles -list_files {.src} $proj_list_dir $repo_path] libraries
460  set toml_file [open "vhdl_ls_$project.toml" w]
461  puts $toml_file "\[libraries\]"
462  dict for {lib source_files} $libraries {
463  puts $toml_file "[file rootname $lib].files = \["
464  foreach source_file $source_files {
465  if {
466  [file extension $source_file] == ".vhd"
467  || [file extension $source_file] == ".vhdl"
468  } {
469  # puts [Relative $repo_path $source_file ]
470  puts $toml_file "\'[Relative $repo_path $source_file]\',"
471  }
472  }
473  puts $toml_file "\]\n"
474  }
475  close $toml_file
476  Msg Info "VHDL-LS TOML File created: vhdl_ls_$project.toml"
477  Msg Info \
478  "You can copy the content of this file into your VHDL-LS configuration vhdl_ls.toml, to import all Hog libraries."
479  exit 0
480  }
481 
482  if {$do_cocotb == 1} {
483  source $tcl_path/utils/cocotb.tcl
484  source $tcl_path/utils/hierarchy.tcl
485  WriteCocoTbTemplate $project_name $repo_path $lib_path $ext_path
486  exit 0
487  }
488 
489  if {$do_check_yaml_ref == 1} {
490  Msg Info "Checking if \"ref\" in .gitlab-ci.yml actually matches the included yml file in Hog submodule"
491  CheckYmlRef $repo_path false
492  exit 0
493  }
494 
495  if {$do_buttons == 1} {
496  Msg Info "Adding Hog buttons to Vivado bar (will use the vivado currently in PATH)..."
497  set ide vivado
498  set cmd "vivado -mode batch -notrace -source $repo_path/Hog/Tcl/utils/add_hog_custom_button.tcl"
499  }
500 
501  if {$do_compile_lib == 1} {
502  if {$project eq ""} {
503  Msg Error "You need to specify a simulator as first argument."
504  exit 1
505  } else {
506  set simulator $project
507  Msg Info "Selecting $simulator simulator..."
508  }
509  if {$options(dst_dir) != ""} {
510  set output_dir $options(dst_dir)
511  } else {
512  Msg Info "No destination directory defined. Using default: SimulationLib/"
513  set output_dir "SimulationLib"
514  }
515 
516  set ide vivado
517  set cmd \
518  "vivado -mode batch -notrace -source $repo_path/Hog/Tcl/utils/compile_simlib.tcl -tclargs -simulator $simulator \
519  -output_dir $output_dir"
520  }
521 
522  set simsets ""
523  if {$do_simulation == 1} {
524  # Filter out HLS simsets (csim:*/cosim:*) -- GHDL only needs HDL simsets
525  set hdl_simsets_pre [list]
526  if {$options(simset) ne ""} {
527  foreach s $options(simset) {
528  if {![regexp {^(csim|cosim):} $s]} {
529  lappend hdl_simsets_pre $s
530  }
531  }
532  }
533 
534  # Get all simsets in the project that run with GHDL
535  set ghdl_simsets [GetSimSets $project_name $repo_path "$hdl_simsets_pre" 1]
536  set ghdl_import 0
537  dict for {simset_name simset_dict} $ghdl_simsets {
538  if {$ghdl_import == 0} {
539  ImportGHDL $project_name $repo_path $simset_name $simset_dict $ext_path
540  set ghdl_import 1
541  }
542  LaunchGHDL $project_name $repo_path $simset_name $simset_dict $ext_path
543  }
544  set ide_simsets [GetSimSets $project_name $repo_path $hdl_simsets_pre 0 1]
545 
546  if {[dict size $ide_simsets] == 0} {
547  # Check if there are HLS simsets to run before exiting
548  set has_hls [expr {$options(simset) eq ""}]
549  if {!$has_hls} {
550  foreach s $options(simset) {
551  if {[regexp {^(csim|cosim):} $s]} {
552  set has_hls 1
553  break
554  }
555  }
556  }
557  if {!$has_hls} {
558  Msg Info "All simulations have been run, exiting..."
559  exit 0
560  }
561  }
562  }
563 
564  if {$do_version == 1} {
565  cd $repo_path
566  set proj_dir $repo_path/Top/$project_name
567  lassign [GetRepoVersions $proj_dir $repo_path $ext_path] sha ver
568  if {$options(describe) == 1} {
569  puts [GetHogDescribe $proj_dir $repo_path]
570  } else {
571  puts "v[HexVersionToString $ver]"
572  }
573  exit 0
574  }
575 
576  # if {$do_new_directive ==1 } {
577  #
578  # # Do things here
579  #
580  # exit 0
581  #}
582  #### END of tclsh commands ####
583  Msg Info "Launching command: $cmd..."
584 
585  # Check if the IDE is actually in the path...
586  set ret [catch {exec which $ide}]
587  if {$ret != 0} {
588  if {[string match "*vitis_unified*" $ide_name]} {
589  Msg Error \
590  "This is a '$ide_name' project: make sure to add both Vivado and Vitis to your PATH environment variable."
591  } else {
592  Msg Error "$ide not found in your system. Make sure to add $ide to your PATH environment variable."
593  }
594  exit $ret
595  }
596 
597  if {[string first libero $cmd] >= 0} {
598  # The SCRIPT_ARGS: flag of libero makes tcl crazy...
599  # Let's pipe the command into a shell script and remove it later
600  set libero_script [open "launch-libero-hog.sh" w]
601  puts $libero_script "#!/bin/sh"
602  puts $libero_script $cmd
603  close $libero_script
604  set cmd "sh launch-libero-hog.sh"
605  }
606 
607  set ret [catch {exec -ignorestderr {*}$cmd >@ stdout 2>@ stderr} result]
608 
609  if {$ret != 0} {
610  Msg Error "IDE returned an error state."
611  } else {
612  Msg Info "All done."
613  exit 0
614  }
615 
616  if {[string first libero $cmd] >= 0} {
617  file delete "launch-libero-hog.sh"
618  }
619 
620  exit $ret
621 }
622 
623 
624 #After this line, we are in the IDE
625 ##################################################################################
626 # We need to Import tcllib if we are using Libero
627 if {[IsLibero] || [IsDiamond]} {
628  if {[info exists env(HOG_TCLLIB_PATH)]} {
629  lappend auto_path $env(HOG_TCLLIB_PATH)
630  } else {
631  puts \
632  "ERROR: To run Hog with Microsemi Libero SoC or Lattice Diamond, you need to define the HOG_TCLLIB_PATH variable."
633  return
634  }
635 }
636 
637 if {[catch {package require cmdline} ERROR] || [catch {package require struct::matrix} ERROR]} {
638  puts \
639  "$ERROR\n Tcllib not found. If you are running this script on tclsh for debuggin purpose ONLY, you can fix this by \
640  installing 'tcllib'"
641  exit 1
642 }
643 
644 set run_folder [file normalize "$repo_path/Projects/$project_name/$project.runs/"]
645 if {[IsLibero]} {
646  set run_folder [file normalize "$repo_path/Projects/$project_name/"]
647 }
648 
649 # Only for quartus, not used otherwise
650 set project_path [file normalize "$repo_path/Projects/$project_name/"]
651 
652 # Get IDE name from project config file
653 if {$allow_empty_proj == 0 || $project_name ne ""} {
654  set proj_conf [ProjectExists $project_name $repo_path]
655 } else {
656  set proj_conf ""
657 }
658 set ide_name_and_ver [string tolower [GetIDEFromConf $proj_conf]]
659 set ide_name [lindex [regexp -all -inline {\S+} $ide_name_and_ver] 0]
660 
661 # Validate IDE name
662 set supported_ides \
663  [list vivado vivado_vitis_classic vivado_vitis_unified vitis_classic vitis_unified quartus planahead libero diamond \
664  ghdl]
665 if {$ide_name ni $supported_ides} {
666  if {$ide_name eq "vitis"} {
667  Msg Error \
668  "The IDE set in hog.conf ('vitis') is not supported. Did you mean 'vitis_unified' or 'vitis_classic'? Supported \
669  IDEs: [join $supported_ides {, }]"
670  } else {
671  Msg Error "The IDE set in hog.conf ('$ide_name') is not supported. Supported IDEs: [join $supported_ides {, }]"
672  }
673  exit 1
674 }
675 
676 # Vitis IDE detection
677 if {
678  ([string tolower $ide_name] eq "vivado_vitis_classic" || [string tolower $ide_name] eq "vitis_classic")
679  && ($options(vivado_only) != 1)
680 } {
681  set globalSettings::vitis_classic 1
682  set globalSettings::vitis_unified 0
683 } elseif {
684  ([string tolower $ide_name] eq "vivado_vitis_unified" || [string tolower $ide_name] eq "vitis_unified")
685  && ($options(vivado_only) != 1)
686 } {
687  set globalSettings::vitis_classic 0
688  set globalSettings::vitis_unified 1
689  if {[auto_execok vitis] eq ""} {
690  Msg Error \
691  "Vitis Unified IDE is required for project $project_name but 'vitis' was not found in PATH. Please source Vitis \
692  settings first."
693  }
694 } else {
695  set globalSettings::vitis_classic 0
696  set globalSettings::vitis_unified 0
697 }
698 
699 # Standalone vitis_unified / vitis_classic projects are implicitly vitis-only
700 if {$ide_name eq "vitis_unified" || $ide_name eq "vitis_classic"} {
701  set options(vitis_only) 1
702 }
703 
704 set is_vitis_ide [expr {$globalSettings::vitis_classic == 1 || $globalSettings::vitis_unified == 1}]
705 set is_build_step [expr {$do_synthesis == 1 || $do_implementation == 1 || $do_compile == 1}]
706 if {$is_vitis_ide && $options(vitis_only) == 1 && $is_build_step} {
707  set do_vitis_build 1
708 }
709 
710 
711 if {$options(no_bitstream) == 1} {
712  set do_bitstream 0
713  set do_compile 0
714 }
715 
716 if {$options(recreate) == 1} {
717  set recreate 1
718 }
719 
720 if {$options(synth_only) == 1} {
721  set do_implementation 0
722  set do_synthesis 1
723  set do_bitstream 0
724  set do_create 1
725  set do_compile 1
726 }
727 
728 if {$options(impl_only) == 1} {
729  set do_implementation 1
730  set do_synthesis 0
731  set do_bitstream 0
732  set do_create 0
733  set do_compile 1
734 }
735 
736 if {$options(vitis_only) == 1 || $ide_name eq "vitis_classic" || $ide_name eq "vitis_unified"} {
737  set do_implementation 0
738  set do_synthesis 0
739  set do_bitstream 0
740  set do_compile 0
741 }
742 
743 if {$options(bitstream_only) == 1} {
744  set do_bitstream_only 1
745  set do_bitstream 0
746  set do_implementation 0
747  set do_synthesis 0
748  set do_create 0
749  set do_compile 0
750 } else {
751  set do_bitstream_only 0
752 }
753 
754 if {$options(no_reset) == 1} {
755  set do_reset 0
756 }
757 
758 if {$options(check_syntax) == 1} {
759  set do_check_syntax 1
760 }
761 
762 if {$options(scripts_only) == 1} {
763  set scripts_only 1
764 }
765 
766 if {$options(compile_only) == 1} {
767  set compile_only 1
768 }
769 
770 
771 Msg Info "Number of jobs set to $options(njobs)."
772 
773 ############## Quartus ########################
774 set argv ""
775 
776 ############# CREATE or OPEN project ############
777 if {$options(vitis_only) == 1 && ($ide_name eq "vitis_unified" || $ide_name eq "vivado_vitis_unified")} {
778  cd $tcl_path
779  set project_file [file normalize $repo_path/Projects/$project_name/vitis_unified/_ide/settings.json]
780  Msg Info "Setting project file for Vitis Unified project $project_name to $project_file"
781 } elseif {$options(vitis_only) == 1 && ($ide_name eq "vitis_classic" || $ide_name eq "vivado_vitis_classic")} {
782  cd $tcl_path
783  set project_file [file normalize $repo_path/Projects/$project_name/vitis_classic/.metadata/]
784  Msg Info "Setting project file for Vitis Classic project $project_name to $project_file"
785 } elseif {[IsISE]} {
786  cd $tcl_path
787  set project_file [file normalize $repo_path/Projects/$project_name/$project.ppr]
788 } elseif {[IsVivado]} {
789  cd $tcl_path
790  set project_file [file normalize $repo_path/Projects/$project_name/$project.xpr]
791 } elseif {[IsVitisClassic]} {
792  cd $tcl_path
793  set project_file [file normalize $repo_path/Projects/$project_name/vitis_classic/.metadata/]
794  Msg Info "Setting project file for Vitis Classic project $project_name to $project_file"
795 } elseif {[IsVitisUnified]} {
796  cd $tcl_path
797  set project_file [file normalize $repo_path/Projects/$project_name/vitis_unified/_ide/settings.json]
798  Msg Info "Setting project file for Vitis Unified project $project_name to $project_file"
799 } elseif {[IsQuartus]} {
800  if {[catch {package require ::quartus::project} ERROR]} {
801  Msg Error "$ERROR\n Can not find package ::quartus::project"
802  cd $old_path
803  return 1
804  } else {
805  Msg Info "Loaded package ::quartus::project"
806  load_package flow
807  }
808  set project_file "$project_path/$project.qpf"
809 } elseif {[IsLibero]} {
810  set project_file [file normalize $repo_path/Projects/$project_name/$project.prjx]
811 } elseif {[IsDiamond]} {
812  sys_install version
813  set project_file [file normalize $repo_path/Projects/$project_name/$project.ldf]
814 } else {
815  Msg Error "Unknown IDE, can't set project file path."
816  exit 1
817 }
818 
819 if {[file exists $project_file]} {
820  Msg Info "Found project file $project_file for $project_name."
821  set proj_found 1
822 } else {
823  # Path from InitLauncher may resolve to a different mount for the same repo.
824  # Discover repo root and use first path where project exists (file or, for Vitis Unified, project dir).
825  set repo_norm [file normalize $repo_path]
826  set rel [string trimleft [string range $project_file [string length $repo_norm] end] "/"]
827  set proj_found 0
828  foreach start_dir [list [file dirname [info script]] [pwd]] {
829  set repo_candidate [FindRepoRoot $start_dir]
830  Msg Debug "FindRepoRoot([list $start_dir]) => [list $repo_candidate]"
831  if {$repo_candidate ne ""} {
832  set project_file_alt [file join $repo_candidate $rel]
833  set found 0
834  if {[file exists $project_file_alt]} {
835  set found 1
836  } elseif {$options(vitis_only) == 1 && [string match "*vitis_unified*" $rel]} {
837  set ide_dir [file join $repo_candidate Projects $project_name vitis_unified _ide]
838  if {[file exists $ide_dir]} {
839  set found 1
840  }
841  }
842  if {$options(vitis_only) == 1 && [string match "*vitis_unified*" $rel]} {
843  Msg Debug \
844  "Checking file [list $project_file_alt] exists=[file exists $project_file_alt]; _ide dir [list $ide_dir] \
845  exists=[file exists $ide_dir]"
846  } else {
847  Msg Debug "Checking [list $project_file_alt] exists=[file exists $project_file_alt]"
848  }
849  if {$found} {
850  set project_file $project_file_alt
851  set repo_path $repo_candidate
852  Msg Info "Found project file $project_file for $project_name."
853  set proj_found 1
854  break
855  }
856  }
857  }
858  if {!$proj_found} {
859  Msg Info "Project file not found for $project_name."
860  }
861 }
862 
863 if {($proj_found == 0 || $recreate == 1)} {
864  set do_create 1
865  Msg Info "Creating (possibly replacing) the project $project_name..."
866  Msg Debug "launch.tcl: calling GetConfFiles with $repo_path/Top/$project_name"
867  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post pre_rtl post_rtl
868 
869  if {[file exists $conf]} {
870  set globalSettings::vitis_only_pass $options(vitis_only)
871  if {$options(vivado_only) == 1} {
872  CreateProject -simlib_path $lib_path -xsa $options(xsa) -vivado_only $project_name $repo_path
873  } elseif {$options(vitis_only) == 1} {
874  CreateProject -simlib_path $lib_path -xsa $options(xsa) -vitis_only $project_name $repo_path
875  } else {
876  CreateProject -simlib_path $lib_path -xsa $options(xsa) $project_name $repo_path
877  }
878  Msg Info "Done creating project $project_name."
879  if {$options(vitis_only) == 1 && ($ide_name eq "vitis_unified" || $ide_name eq "vivado_vitis_unified")} {
880  set project_file [file join $repo_path Projects $project_name vitis_unified _ide settings.json]
881  }
882  } else {
883  Msg Error "Project $project_name is incomplete: no hog.conf file found, please create one..."
884  }
885 } elseif {$proj_found == 0} {
886  Msg Error "Project $project_name not found. Please create it first using the 'CREATE' or 'C' directive."
887  exit 1
888 } else {
889  Msg Info "Opening existing project file $project_file..."
890  if {$options(vitis_only) == 1 && ($ide_name eq "vitis_unified" || $ide_name eq "vivado_vitis_unified")} {
891  set vitis_workspace [file normalize $repo_path/Projects/$project_name/vitis_unified/]
892  Msg Info "Setting Vitis Unified workspace to $vitis_workspace"
893  } elseif {[IsXilinx]} {
894  file mkdir "$repo_path/Projects/$project_name/$project.gen/sources_1"
895  OpenProject $project_file $repo_path
896  } elseif {[IsVitisClassic]} {
897  set vitis_workspace [file normalize $repo_path/Projects/$project_name/vitis_classic/]
898  Msg Info "Setting workspace to $vitis_workspace"
899  } elseif {[IsVitisUnified]} {
900  set vitis_workspace [file normalize $repo_path/Projects/$project_name/vitis_unified/]
901  Msg Info "Setting workspace to $vitis_workspace"
902  } else {
903  OpenProject $project_file $repo_path
904  }
905 }
906 
907 
908 ########## CHECK SYNTAX ###########
909 if {$do_check_syntax == 1} {
910  if {$ide_name eq "vitis_unified" || $ide_name eq "vitis_classic"} {
911  Msg Info "Skipping syntax check for $project_name: pure Vitis project has no HDL syntax to check"
912  } else {
913  Msg Info "Checking syntax for project $project_name..."
914  CheckSyntax $project_name $repo_path $project_file
915  }
916 }
917 
918 ######### RTL ANALYSIS ########
919 if {$do_rtl == 1} {
920  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post pre_rtl post_rtl
921  LaunchRTLAnalysis $repo_path $pre_rtl $post_rtl
922 }
923 
924 if {$do_vitis_build == 1} {
925  if {[IsVitisClassic] || [IsVitisUnified]} {
926  # Check for HLS components and build them
927  set conf_file_path [file normalize "$repo_path/Top/$project_name/hog.conf"]
928  if {[file exists $conf_file_path]} {
929  set proj_properties [ReadConf $conf_file_path]
930  set hls_components [dict filter $proj_properties key {hls:*}]
931  if {[dict size $hls_components] > 0} {
932  Msg Info "Found [dict size $hls_components] HLS component(s), launching HLS build..."
933  LaunchHlsBuild $project_name $repo_path
934  }
935  # Build apps/platforms if any exist
936  set has_apps [expr {[dict size [dict filter $proj_properties key {app:*}]] > 0}]
937  if {$has_apps} {
938  LaunchVitisBuild $project_name $repo_path
939  }
940  } else {
941  LaunchVitisBuild $project_name $repo_path
942  }
943  } else {
944  Msg Error "Vitis build is not supported for $ide_name (only Vitis Classic and Vitis Unified are supported)"
945  exit 1
946  }
947 }
948 
949 ######### LaunchSynthesis ########
950 if {$do_synthesis == 1} {
951  LaunchSynthesis $do_reset $do_create $run_folder $project_name $repo_path $ext_path $options(njobs)
952 }
953 
954 if {$do_implementation == 1} {
955  LaunchImplementation $do_reset $do_create $run_folder $project_name $repo_path $options(njobs) $do_bitstream
956 }
957 
958 if {$do_bitstream_only == 1 && [IsXilinx]} {
959  GenerateBitstreamOnly $project_name $repo_path
960 } elseif {$do_bitstream_only == 1 && ![IsXilinx]} {
961  Msg Error "Bitstream only option is not supported for this IDE."
962 }
963 
964 if {$do_bitstream == 1 && ![IsXilinx]} {
965  GenerateBitstream $run_folder $repo_path $options(njobs)
966 }
967 
968 if {$do_simulation == 1} {
969  # Separate HLS simsets (csim:*/cosim:*) from HDL simsets
970  set hdl_simsets [list]
971  set hls_simsets [list]
972  if {$options(simset) ne ""} {
973  foreach s $options(simset) {
974  if {[regexp {^(csim|cosim):} $s]} {
975  lappend hls_simsets $s
976  } else {
977  lappend hdl_simsets $s
978  }
979  }
980  }
981  set run_hdl [expr {[llength $hdl_simsets] > 0 || $options(simset) eq ""}]
982  set run_hls [expr {[llength $hls_simsets] > 0 || $options(simset) eq ""}]
983 
984  # Run HDL simulations
985  if {$run_hdl} {
986  set simsets [GetSimSets $project_name $repo_path $hdl_simsets]
987  if {[dict size $simsets] > 0} {
988  LaunchSimulation $project_name $lib_path $simsets $repo_path $scripts_only $compile_only
989  }
990  }
991 
992  # Run HLS simulations (csim/cosim)
993  if {$run_hls} {
994  LaunchHlsSimulation $project_name $repo_path $hls_simsets
995  }
996 }
997 
998 
999 if {$do_check_list_files} {
1000  Msg Info "Running list file checker..."
1001 
1002 
1003  #if {![file exists $dst_dir]} {
1004  # Msg Info "$dst_dir directory not found, creating it..."
1005  # file mkdir $dst_dir
1006  # }
1007  set argv0 check_list_files
1008  if {$ext_path ne ""} {
1009  set argv [list "-ext_path" "$ext_path" "-outDir" "$dst_dir" "-pedantic"]
1010  } else {
1011  set argv [list "-outDir" "$dst_dir" "-pedantic"]
1012  }
1013 
1014  source $tcl_path/utils/check_list_files.tcl
1015 }
1016 ## CLOSE Project
1018 
1019 Msg Info "All done."
1020 cd $old_path