Hog v9.67.0
create_project.tcl
Go to the documentation of this file.
1 # Copyright 2018-2025 The University of Birmingham
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 ## @file create_project.tcl
16 # @brief contains all functions needed to create a new project
17 # @todo This file will need to be fully documented
18 #
19 
20 
21 ##nagelfar variable quartus
22 
23 ## @namespace globalSettings
24 # @brief Namespace of all the project settings
25 #
26 # Variables in upper case are expected to be passed by the caller.
27 # Variables lower case are evaluated in the script defined in create_project.tcl
28 #
29 namespace eval globalSettings {
30  #The project name (including flavour if any)
31  variable DESIGN
32 
33  variable PART
34 
35  # Quartus only
36  variable FAMILY
37  # Libero only
38  variable DIE
39  variable PACKAGE
40  variable ADV_OPTIONS
41  variable SPEED
42  variable LIBERO_MANDATORY_VARIABLES
43  # Diamond only
44  variable DEVICE
45 
46  variable PROPERTIES
47  variable HOG_EXTERNAL_PATH
48  variable HOG_IP_PATH
49  variable TARGET_SIMULATOR
50 
51  variable pre_synth_file
52  variable post_synth_file
53  variable pre_impl_file
54  variable post_impl_file
55  variable pre_bit_file
56  variable post_bit_file
57  variable quartus_post_module_file
58  variable tcl_path
59  variable repo_path
60  variable top_path
61  variable list_path
62  variable build_dir
63  variable simlib_path
64  variable top_name
65  variable synth_top_module
66  variable user_ip_repo
67 
68  variable vitis_classic
69  variable pre_synth
70  variable post_synth
71  variable pre_impl
72  variable post_impl
73  variable pre_bit
74  variable post_bit
75  variable quartus_post_module
76 }
77 
78 ################# FUNCTIONS ################################
79 proc InitProject {} {
80  if {[IsXilinx]} {
81  if {[IsVivado]} {
82  # Suppress unnecessary warnings
83  # tclint-disable-next-line line-length
84  set_msg_config -suppress -regexp -string {".*The IP file '.*' has been moved from its original location, as a result the outputs for this IP will now be generated in '.*'. Alternatively a copy of the IP can be imported into the project using one of the 'import_ip' or 'import_files' commands..*"}
85  set_msg_config -suppress -regexp -string {".*File '.*.xci' referenced by design '.*' could not be found..*"}
86 
87  # File inside .bd
88  set_msg_config -suppress -id {IP_Flow 19-3664}
89  # This is due to simulations in project with NoC
90  # tclint-disable-next-line line-length
91  set_msg_config -suppress -id {Vivado 12-23660} -string {{ERROR: [Vivado 12-23660] Simulation is not supported for the target language VHDL when design contains NoC (Network-on-Chip) blocks} }
92  }
93  # Create project
94  create_project -force [file tail $globalSettings::DESIGN] $globalSettings::build_dir -part $globalSettings::PART
95  file mkdir "$globalSettings::build_dir/[file tail $globalSettings::DESIGN].gen/sources_1"
96  if {[IsVersal $globalSettings::PART]} {
97  Msg Info "This project uses a Versal device."
98  }
99 
100  ## Set project properties
101  set obj [get_projects [file tail $globalSettings::DESIGN]]
102  set_property "target_language" "VHDL" $obj
103 
104  if {[IsVivado]} {
105  set_property "simulator_language" "Mixed" $obj
106  foreach simulator [GetSimulators] {
107  set_property "compxlib.${simulator}_compiled_library_dir" $globalSettings::simlib_path $obj
108  }
109  set_property "default_lib" "xil_defaultlib" $obj
110  ## Enable VHDL 2008
111  set_param project.enableVHDL2008 1
112  set_property "enable_vhdl_2008" 1 $obj
113  ## Enable Automatic compile order mode, otherwise we cannot find the right top module...
114  set_property source_mgmt_mode All [current_project]
115  # Set PART Immediately
116  Msg Debug "Setting PART = $globalSettings::PART"
117  set_property PART $globalSettings::PART [current_project]
118  }
119 
121  } elseif {[IsQuartus]} {
122  package require ::quartus::project
123  #QUARTUS_ONLY
124  if {[string equal $globalSettings::FAMILY "quartus_only"]} {
125  Msg Error "You must specify a device Family for Quartus"
126  } else {
127  file mkdir $globalSettings::build_dir
128  cd $globalSettings::build_dir
129  if {[is_project_open]} {
130  project_close
131  }
132 
133  file delete {*}[glob -nocomplain $globalSettings::DESIGN.q*]
134 
135  project_new -family $globalSettings::FAMILY -overwrite -part $globalSettings::PART $globalSettings::DESIGN
136  set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
137 
139  }
140  } elseif {[IsLibero]} {
141  if {[file exists $globalSettings::build_dir]} {
142  file delete -force $globalSettings::build_dir
143  }
144  new_project -location $globalSettings::build_dir \
145  -name [file tail $globalSettings::DESIGN] \
146  -die $globalSettings::DIE \
147  -package $globalSettings::PACKAGE \
148  -family $globalSettings::FAMILY \
149  -hdl VHDL
150  } elseif {[IsDiamond]} {
151  if {[file exists $globalSettings::build_dir]} {
152  file delete -force $globalSettings::build_dir
153  }
154  set old_dir [pwd]
155  file mkdir $globalSettings::build_dir
156  cd $globalSettings::build_dir
157  prj_project new -name [file tail $globalSettings::DESIGN] -dev $globalSettings::DEVICE -synthesis $globalSettings::SYNTHESIS_TOOL
158  cd $old_dir
160  } elseif {[IsVitisClassic]} {
161  if {[file exists $globalSettings::build_dir/vitis_classic]} {
162  file delete -force $globalSettings::build_dir/vitis_classic
163  }
164  setws $globalSettings::build_dir/vitis_classic
165  } else {
166  puts "Creating project for $globalSettings::DESIGN part $globalSettings::PART"
167  puts "Configuring project settings:"
168  puts " - simulator_language: Mixed"
169  puts " - target_language: VHDL"
170  puts " - simulator: QuestaSim"
171  puts "Adding IP directory \"$globalSettings::user_ip_repo\" to the project "
172  }
173 }
174 
175 proc AddProjectFiles {} {
176  if {[IsXilinx]} {
177  #VIVADO_ONLY
178  ## Create fileset src
179  if {[string equal [get_filesets -quiet sources_1] ""]} {
180  create_fileset -srcset sources_1
181  }
182  set sources "sources_1"
183  } else {
184  set sources 0
185  }
186 
187 
188  ###############
189  # CONSTRAINTS #
190  ###############
191  if {[IsXilinx]} {
192  #VIVADO_ONLY
193  # Create 'constrs_1' fileset (if not found)
194  if {[string equal [get_filesets -quiet constrs_1] ""]} {
195  create_fileset -constrset constrs_1
196  }
197 
198  # Set 'constrs_1' fileset object
199  set constraints [get_filesets constrs_1]
200  }
201 
202  ##############
203  # READ FILES #
204  ##############
205 
206  if {[file isdirectory $globalSettings::list_path]} {
207  set list_files [glob -directory $globalSettings::list_path "*"]
208  } else {
209  Msg Error "No list directory found at $globalSettings::list_path"
210  }
211 
212  if {[IsISE]} {
213  source $globalSettings::tcl_path/utils/cmdline.tcl
214  }
215 
216  # Add first .src, .sim, and .ext list files
217  AddHogFiles {*}[GetHogFiles -list_files {.src,.sim,.ext} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path]
218 
219  ## Set synthesis TOP
220  SetTopProperty $globalSettings::synth_top_module $sources
221 
222  # Libero needs the top files to be set before adding the constraints
223  AddHogFiles {*}[GetHogFiles -list_files {.con} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path]
224  ## Set simulation Properties
225 
226  ## Libero Properties must be set after that root has been defined
227  if {[IsLibero]} {
229  }
230 }
231 
232 
233 ## @brief Set Vivado Report strategy for implementation
234 #
235 # @param[in] obj the project object
236 #
237 proc CreateReportStrategy {obj} {
238  #TODO: Add ReportStrategy for Quartus/Libero and Diamond
239 
240  if {[IsVivado]} {
241  ## Vivado Report Strategy
242  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
243  # No report strategy needed
244  Msg Info "No report strategy needed for implementation"
245  } else {
246  # Report strategy needed since version 2017.3
247  set_property set_report_strategy_name 1 $obj
248  set_property report_strategy {Vivado Implementation Default Reports} $obj
249  set_property set_report_strategy_name 0 $obj
250 
251  set reports [get_report_configs -of_objects $obj]
252  # Create 'impl_1_place_report_utilization_0' report (if not found)
253  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] ""]} {
254  create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1
255  }
256  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0]
257  if {$obj != ""} {
258 
259  }
260 
261  # Create 'impl_1_route_report_drc_0' report (if not found)
262  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] ""]} {
263  create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1
264  }
265  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0]
266  if {$obj != ""} {
267 
268  }
269 
270  # Create 'impl_1_route_report_power_0' report (if not found)
271  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] ""]} {
272  create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1
273  }
274  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0]
275  if {$obj != ""} {
276 
277  }
278 
279  # Create 'impl_1_route_report_timing_summary' report (if not found)
280  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary] ""]} {
281  create_report_config -report_name impl_1_route_report_timing_summary -report_type report_timing_summary:1.0 -steps route_design -runs impl_1
282  }
283  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary]
284  if {$obj != ""} {
285  Msg Info "Report timing created successfully"
286  }
287 
288  # Create 'impl_1_route_report_utilization' report (if not found)
289  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization] ""]} {
290  create_report_config -report_name impl_1_route_report_utilization -report_type report_utilization:1.0 -steps route_design -runs impl_1
291  }
292  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization]
293  if {$obj != ""} {
294  Msg Info "Report utilization created successfully"
295  }
296 
297 
298  # Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found)
299  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] ""]} {
300  create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 \
301  -report_type report_timing_summary:1.0 \
302  -steps post_route_phys_opt_design -runs impl_1
303  }
304  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0]
305  if {$obj != ""} {
306  set_property -name "options.max_paths" -value "10" -objects $obj
307  set_property -name "options.warn_on_violation" -value "1" -objects $obj
308  }
309  }
310  } else {
311  Msg Info "Won't create any report strategy, not in Vivado"
312  }
313 }
314 
315 
316 ## @brief configure synthesis.
317 #
318 # The method uses the content of globalSettings::SYNTH_FLOW and globalSettings::SYNTH_STRATEGY to set the implementation strategy and flow.
319 # The function also sets Hog specific pre and post synthesis scripts
320 #
321 proc ConfigureSynthesis {} {
322  if {[IsXilinx]} {
323  #VIVADO ONLY
324  ## Create 'synthesis ' run (if not found)
325  if {[string equal [get_runs -quiet synth_1] ""]} {
326  create_run -name synth_1 -part $globalSettings::PART -constrset constrs_1
327  } else {
328 
329  }
330 
331  set obj [get_runs synth_1]
332  set_property "part" $globalSettings::PART $obj
333  }
334 
335  ## set pre synthesis script
336  if {$globalSettings::pre_synth_file ne ""} {
337  if {[IsXilinx]} {
338  #Vivado Only
339  if {[IsVivado]} {
340  if {[get_filesets -quiet utils_1] != ""} {
341  AddFile $globalSettings::pre_synth [get_filesets -quiet utils_1]
342  }
343  set_property STEPS.SYNTH_DESIGN.TCL.PRE $globalSettings::pre_synth $obj
344  }
345  } elseif {[IsQuartus]} {
346  #QUARTUS only
347  set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_synth
348  } elseif {[IsLibero]} {
349  configure_tool -name {SYNTHESIZE} -params SYNPLIFY_TCL_FILE:$globalSettings::pre_synth
350  } elseif {[IsDiamond]} {
351  prj_impl pre_script "syn" $globalSettings::pre_synth
352  }
353 
354  Msg Debug "Setting $globalSettings::pre_synth to be run before synthesis"
355  }
356 
357  ## set post synthesis script
358  if {$globalSettings::post_synth_file ne ""} {
359  if {[IsXilinx]} {
360  #Vivado Only
361  if {[IsVivado]} {
362  if {[get_filesets -quiet utils_1] != ""} {
363  AddFile $globalSettings::post_synth [get_filesets -quiet utils_1]
364  }
365  set_property STEPS.SYNTH_DESIGN.TCL.POST $globalSettings::post_synth $obj
366  }
367  } elseif {[IsQuartus]} {
368  #QUARTUS only
369  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
370  } elseif {[IsDiamond]} {
371  prj_impl post_script "syn" $globalSettings::post_synth
372  }
373  Msg Debug "Setting $globalSettings::post_synth to be run after synthesis"
374  }
375 
376 
377  if {[IsXilinx]} {
378  #VIVADO ONLY
379  ## set the current synth run
380  current_run -synthesis $obj
381 
382  ## Report Strategy
383  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
384  # No report strategy needed
385  Msg Debug "No report strategy needed for synthesis"
386  } else {
387  # Report strategy needed since version 2017.3
388  set_property set_report_strategy_name 1 $obj
389  set_property report_strategy {Vivado Synthesis Default Reports} $obj
390  set_property set_report_strategy_name 0 $obj
391  # Create 'synth_1_synth_report_utilization_0' report (if not found)
392  if {[string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] ""]} {
393  create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1
394  }
395  set reports [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]
396  }
397  } elseif {[IsQuartus]} {
398  #QUARTUS only
399  #TO BE DONE
400  } elseif {[IsLibero]} {
401  #TODO: LIBERO
402  } elseif {[IsDiamond]} {
403  #TODO: Diamond
404  } else {
405  Msg info "Reporting strategy for synthesis"
406  }
407 }
408 
409 ## @brief configure implementation.
410 #
411 # The configuration is based on the content of globalSettings::IMPL_FLOW and globalSettings::IMPL_STRATEGY
412 # The function also sets Hog specific pre- and- post implementation and, pre- and post- implementation scripts
413 #
414 proc ConfigureImplementation {} {
415  set obj ""
416  if {[IsXilinx]} {
417  # Create 'impl_1' run (if not found)
418  if {[string equal [get_runs -quiet impl_1] ""]} {
419  create_run -name impl_1 -part $globalSettings::PART -constrset constrs_1 -parent_run synth_1
420  }
421 
422  set obj [get_runs impl_1]
423  set_property "part" $globalSettings::PART $obj
424 
425  set_property "steps.[BinaryStepName $globalSettings::PART].args.readback_file" "0" $obj
426  set_property "steps.[BinaryStepName $globalSettings::PART].args.verbose" "0" $obj
427  } elseif {[IsQuartus]} {
428  #QUARTUS only
429  set obj ""
430  }
431 
432 
433  ## set pre implementation script
434  if {$globalSettings::pre_impl_file ne ""} {
435  if {[IsXilinx]} {
436  #Vivado Only
437  if {[IsVivado]} {
438  if {[get_filesets -quiet utils_1] != ""} {
439  AddFile $globalSettings::pre_impl [get_filesets -quiet utils_1]
440  }
441  set_property STEPS.INIT_DESIGN.TCL.POST $globalSettings::pre_impl $obj
442  }
443  } elseif {[IsQuartus]} {
444  #QUARTUS only
445  #set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_impl
446  } elseif {[IsDiamond]} {
447  prj_impl pre_script "par" $globalSettings::pre_impl
448  }
449  Msg Debug "Setting $globalSettings::pre_impl to be run after implementation"
450  }
451 
452 
453  ## set post routing script
454  if {$globalSettings::post_impl_file ne ""} {
455  if {[IsXilinx]} {
456  #Vivado Only
457  if {[IsVivado]} {
458  if {[get_filesets -quiet utils_1] != ""} {
459  AddFile $globalSettings::post_impl [get_filesets -quiet utils_1]
460  }
461  set_property STEPS.ROUTE_DESIGN.TCL.POST $globalSettings::post_impl $obj
462  }
463  } elseif {[IsQuartus]} {
464  #QUARTUS only
465  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
466  } elseif {[IsDiamond]} {
467  prj_impl post_script "par" $globalSettings::post_impl
468  }
469  Msg Debug "Setting $globalSettings::post_impl to be run after implementation"
470  }
471 
472  ## set pre write bitstream script
473  if {$globalSettings::pre_bit_file ne ""} {
474  if {[IsXilinx]} {
475  #Vivado Only
476  if {[IsVivado]} {
477  if {[get_filesets -quiet utils_1] != ""} {
478  AddFile $globalSettings::pre_bit [get_filesets -quiet utils_1]
479  }
480  set_property STEPS.[BinaryStepName $globalSettings::PART].TCL.PRE $globalSettings::pre_bit $obj
481  }
482  } elseif {[IsQuartus]} {
483  #QUARTUS only
484  #set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_bit
485  } elseif {[IsDiamond]} {
486  prj_impl pre_script "export" $globalSettings::pre_bit
487  }
488  Msg Debug "Setting $globalSettings::pre_bit to be run after bitfile generation"
489  }
490 
491  ## set post write bitstream script
492  if {$globalSettings::post_bit_file ne ""} {
493  if {[IsXilinx]} {
494  #Vivado Only
495  if {[IsVivado]} {
496  if {[get_filesets -quiet utils_1] != ""} {
497  AddFile $globalSettings::post_bit [get_filesets -quiet utils_1]
498  }
499  set_property STEPS.[BinaryStepName $globalSettings::PART].TCL.POST $globalSettings::post_bit $obj
500  }
501  } elseif {[IsQuartus]} {
502  #QUARTUS only
503  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
504  } elseif {[IsDiamond]} {
505  prj_impl post_script "export" $globalSettings::post_bit
506  }
507  Msg Debug "Setting $globalSettings::post_bit to be run after bitfile generation"
508  }
509 
511 }
512 
513 
514 ## @brief configure simulation
515 #
516 proc ConfigureSimulation {} {
517  set simsets_dict [GetSimSets "$globalSettings::group_name/$globalSettings::DESIGN" $globalSettings::repo_path]
518 
519  if {[IsXilinx]} {
520  ##############
521  # SIMULATION #
522  ##############
523  Msg Debug "Setting load_glbl parameter to true for every fileset..."
524  foreach simset [get_filesets -quiet] {
525  if {[get_property FILESET_TYPE $simset] != "SimulationSrcs"} {
526  continue
527  }
528  if {[IsVivado]} {
529  set_property -name {xsim.elaborate.load_glbl} -value {true} -objects [get_filesets $simset]
530  }
531  # Setting Simulation Properties
532  set sim_dict [DictGet $simsets_dict $simset]
533  set sim_props [DictGet $sim_dict "properties"]
534 
535  if {$sim_props != ""} {
536  Msg Info "Setting properties for simulation set: $simset..."
537  dict for {prop_name prop_val} $sim_props {
538  set prop_name [string toupper $prop_name]
539  if {$prop_name == "ACTIVE" && $prop_val == 1} {
540  Msg Info "Setting $simset as active simulation set..."
541  current_fileset -simset [get_filesets $simset]
542  } else {
543  Msg Debug "Setting $prop_name = $prop_val"
544  if {[IsInList [string toupper $prop_name] [VIVADO_PATH_PROPERTIES] 1]} {
545  # Check that the file exists before setting these properties
546  if {[file exists $globalSettings::repo_path/$prop_val]} {
547  set_property $prop_name $globalSettings::repo_path/$prop_val [get_filesets $simset]
548  } else {
549  Msg Warning "Impossible to set property $prop_name to $prop_val. File is missing"
550  }
551  } else {
552  set_property $prop_name $prop_val [get_filesets $simset]
553  }
554  }
555  }
556  }
557  }
558  }
559 }
560 
561 ## @brief uses the content of globalSettings::PROPERTIES to set additional project properties
562 #
563 proc ConfigureProperties {} {
564  set cur_dir [pwd]
565  cd $globalSettings::repo_path
566  if {[IsXilinx]} {
567  set user_repo "0"
568  # Setting Main Properties
569  if {[info exists globalSettings::PROPERTIES]} {
570  if {[dict exists $globalSettings::PROPERTIES main]} {
571  Msg Info "Setting project-wide properties..."
572  set proj_props [dict get $globalSettings::PROPERTIES main]
573  dict for {prop_name prop_val} $proj_props {
574  if {[string tolower $prop_name] != "ip_repo_paths"} {
575  if {[string tolower $prop_name] != "part"} {
576  # Part is already set
577  Msg Debug "Setting $prop_name = $prop_val"
578  set_property $prop_name $prop_val [current_project]
579  }
580  } else {
581  set ip_repo_list [regsub -all {\s+} $prop_val " $globalSettings::repo_path/"]
582  set ip_repo_list $globalSettings::repo_path/$ip_repo_list
583  set user_repo "1"
584  Msg Info "Setting $ip_repo_list as user IP repository..."
585  if {[IsISE]} {
586  set_property ip_repo_paths "$ip_repo_list" [current_fileset]
587  } else {
588  set_property ip_repo_paths "$ip_repo_list" [current_project]
589  }
590  update_ip_catalog
591  }
592  }
593  }
594  # Setting Run Properties
595  foreach run [get_runs -quiet] {
596  if {[dict exists $globalSettings::PROPERTIES $run]} {
597  Msg Info "Setting properties for run: $run..."
598  set run_props [dict get $globalSettings::PROPERTIES $run]
599  #set_property -dict $run_props $run
600  set stragety_str "STRATEGY strategy Strategy"
601  Msg Debug "Setting Strategy and Flow for run $run (if specified in hog.conf)"
602  foreach s $stragety_str {
603  if {[dict exists $run_props $s]} {
604  set prop [dict get $run_props $s]
605  set_property $s $prop $run
606  set run_props [dict remove $run_props $s]
607  Msg Warning "A strategy for run $run has been defined inside hog.conf. This prevents Hog to compare the project properties. \
608  Please regenerate your hog.conf file using the dedicated Hog button."
609  Msg Info "Setting $s = $prop"
610  }
611  }
612 
613  dict for {prop_name prop_val} $run_props {
614  Msg Debug "Setting $prop_name = $prop_val"
615  if {[string trim $prop_val] == ""} {
616  Msg Warning "Property $prop_name has empty value. Skipping..."
617  continue
618  }
619  if {[IsInList [string toupper $prop_name] [VIVADO_PATH_PROPERTIES] 1]} {
620  # Check that the file exists before setting these properties
621  set utility_file $globalSettings::repo_path/$prop_val
622  if {[file exists $utility_file]} {
623  lassign [GetHogFiles -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path] lib prop dummy
624  foreach {l f} $lib {
625  foreach ff $f {
626  lappend hog_files $ff
627  }
628  }
629  if {[lsearch $hog_files $utility_file] < 0} {
630  Msg CriticalWarning "The file: $utility_file is set as a property in hog.conf, \
631  but is not added to the project in any list file. Hog cannot track it."
632  } else {
633  #Add file tu utils_1 to avoid warning
634  AddFile $globalSettings::repo_path/$prop_val [get_filesets -quiet utils_1]
635  }
636  set_property $prop_name $utility_file $run
637  } else {
638  Msg Warning "Impossible to set property $prop_name to $prop_val. File is missing"
639  }
640  } else {
641  set_property $prop_name $prop_val $run
642  }
643  }
644  }
645  }
646  }
647  } elseif {[IsQuartus]} {
648  #QUARTUS only
649  #TO BE DONE
650  } elseif {[IsLibero]} {
651  # Setting Properties
652  if {[info exists globalSettings::PROPERTIES]} {
653  # Device Properties
654  if {[dict exists $globalSettings::PROPERTIES main]} {
655  Msg Info "Setting device properties..."
656  set dev_props [dict get $globalSettings::PROPERTIES main]
657  dict for {prop_name prop_val} $dev_props {
658  if {!([string toupper $prop_name] in $globalSettings::LIBERO_MANDATORY_VARIABLES)} {
659  Msg Debug "Setting $prop_name = $prop_val"
660  set_device -[string tolower $prop_name] $prop_val
661  }
662  }
663  }
664  # Project Properties
665  if {[dict exists $globalSettings::PROPERTIES project]} {
666  Msg Info "Setting project-wide properties..."
667  set dev_props [dict get $globalSettings::PROPERTIES project]
668  dict for {prop_name prop_val} $dev_props {
669  Msg Debug "Setting $prop_name = $prop_val"
670  project_settings -[string tolower $prop_name] $prop_val
671  }
672  }
673  # Synthesis Properties
674  if {[dict exists $globalSettings::PROPERTIES synth]} {
675  Msg Info "Setting Synthesis properties..."
676  set synth_props [dict get $globalSettings::PROPERTIES synth]
677  dict for {prop_name prop_val} $synth_props {
678  Msg Debug "Setting $prop_name = $prop_val"
679  configure_tool -name {SYNTHESIZE} -params "[string toupper $prop_name]:$prop_val"
680  }
681  }
682  # Implementation Properties
683  if {[dict exists $globalSettings::PROPERTIES impl]} {
684  Msg Info "Setting Implementation properties..."
685  set impl_props [dict get $globalSettings::PROPERTIES impl]
686  dict for {prop_name prop_val} $impl_props {
687  Msg Debug "Setting $prop_name = $prop_val"
688  configure_tool -name {PLACEROUTE} -params "[string toupper $prop_name]:$prop_val"
689  }
690  }
691 
692  # Bitstream Properties
693  if {[dict exists $globalSettings::PROPERTIES bitstream]} {
694  Msg Info "Setting Bitstream properties..."
695  set impl_props [dict get $globalSettings::PROPERTIES impl]
696  dict for {prop_name prop_val} $impl_props {
697  Msg Debug "Setting $prop_name = $prop_val"
698  configure_tool -name {GENERATEPROGRAMMINGFILE} -params "[string toupper $prop_name]:$prop_val"
699  }
700  }
701  # Configure VERIFYTIMING tool to generate a txt file report
702  configure_tool -name {VERIFYTIMING} -params {FORMAT:TEXT}
703  }
704  } elseif {[IsDiamond]} {
705  if {[info exists globalSettings::PROPERTIES]} {
706  # Project (main) Properties
707  if {[dict exists $globalSettings::PROPERTIES main]} {
708  Msg Info "Setting project-wide properties..."
709  set dev_props [dict get $globalSettings::PROPERTIES main]
710  dict for {prop_name prop_val} $dev_props {
711  # Device is already set
712  if {[string toupper $prop_name] != "DEVICE"} {
713  Msg Debug "Setting $prop_name = $prop_val"
714  prj_project option $prop_name $prop_val
715  }
716  }
717  }
718  # Implementation properties
719  if {[dict exists $globalSettings::PROPERTIES impl]} {
720  Msg Info "Setting Implementation properties..."
721  set dev_props [dict get $globalSettings::PROPERTIES impl]
722  dict for {prop_name prop_val} $dev_props {
723  # Device is already set
724  Msg Debug "Setting $prop_name = $prop_val"
725  prj_impl option $prop_name $prop_val
726  }
727  }
728  }
729  } else {
730  Msg info "Configuring Properties"
731  }
732  cd $cur_dir
733 }
734 
735 
736 proc ConfigurePlatforms {{xsa ""}} {
737  dict for {key value} [dict filter $globalSettings::PROPERTIES key {platform:*}] {
738  set value_lower [dict create]
739  dict for {vkey vvalue} $value {
740  dict set value_lower [string tolower $vkey] $vvalue
741  }
742  dict set platforms $key $value_lower
743  }
744 
745  set platforms2 [GetPlatformsFromProps $globalSettings::PROPERTIES 0 1]
746  Msg Info "Platform Names: [GetPlatformsFromProps $globalSettings::PROPERTIES 1 1]"
747 
748  dict for {key value} $platforms2 {
749  Msg Info "Key: $key, Value: $value"
750  }
751 
752  if {[dict size $platforms] == 0} {
753  Msg Info "No platforms found in the configuration file"
754  return
755  }
756 
757  dict for {platform_key platform_config} $platforms {
758  Msg Info "Found platform with key: $platform_key with configuration: $platform_config"
759  if {[regexp {^platform:(.+)$} $platform_key -> platform_name]} {
760  set platform_name [string trim $platform_name]
761  Msg Info "Configuring platform: $platform_name"
762  CreatePlatform $platform_name $platform_config $xsa
763  } else {
764  Msg Warning "Invalid platform key format: $platform_key. Expected format: platform:<name>"
765  }
766  }
767 }
768 
769 proc CreatePlatform {platform_name platform_conf {xsa ""}} {
770 
771  set platform_create_options {
772  "desc" "hw" "out" "prebuilt" "proc" "arch"
773  "samples" "os" "xpfm" "no-boot-bsp"
774  }
775 
776  Msg Info "Creating platform configuration..."
777  append platform_options " -name $platform_name"
778 
779  # Remove existing platform if it exists
780  if {[catch {set ws_platforms [platform list -dict]}]} { set ws_platforms "" }
781  if {[lsearch -exact $ws_platforms $platform_name] != -1} {
782  Msg Info "Platform $platform_name already exists, removing it..."
783  platform remove $platform_name
784  }
785 
786  dict for {p v} $platform_conf {
787  if {[IsInList [string toupper $p] [VITIS_PATH_PROPERTIES] 1]} {
788 
789  if {[IsRelativePath $v] == 1} {
790  set v "$globalSettings::repo_path/$v"
791  }
792 
793  if {[file exists $v]} {
794  if {$p == "hw"} {
795  set xsa $v
796  }
797  } else {
798  Msg Warning "Impossible to set property $p to $v. File is missing"
799  continue;
800  }
801  }
802 
803  set p_lower [string tolower $p]
804  if {[IsInList $p_lower $platform_create_options]} {
805  append platform_options " -$p_lower $v"
806  } else {
807  if {$p_lower ne "bif"} {
808  Msg Warning "Attempting to use unknown platform option: $p_lower"
809  append platform_options " -$p_lower $v"
810  }
811  }
812  }
813 
814 
815  # If hw is not in platform conf, use vivado presynth xsa
816  if {![dict exists $platform_conf hw]} {
817  set xsa "$globalSettings::build_dir/$globalSettings::DESIGN-presynth.xsa"
818  set platform_options "$platform_options -hw $xsa"
819  } else {
820  set platform_options "$platform_options"
821  }
822 
823 
824  Msg Info "Opening hardware design to check if proc to cell mapping needs to be extracted for soft processors..."
825  hsi::open_hw_design $xsa
826 
827  set proc_cells [hsi::get_cells -filter { IP_TYPE == "PROCESSOR" }]
828  set proc_map_file [open "$globalSettings::build_dir/vitis_classic/$platform_name.PROC_MAP" "w"]
829 
830  foreach proc $proc_cells {
831  # If soft processor, save mapping from proc to cell to be used later when updating mem
832  Msg Debug "Processor found in xsa: $proc"
833  if {[regexp -nocase {microblaze|risc} $proc]} {
834  Msg Info "Extracting processor cells for soft processor: $proc"
835  set proc_hier_name [hsi::get_property HIER_NAME $proc]
836  set proc_address_tag [hsi::get_property ADDRESS_TAG $proc]
837 
838  if {$proc_address_tag eq ""} {
839  Msg Warning "Processor $proc ($proc_hier_name) does not have an ADDRESS_TAG property set. \
840  This may cause issues when configuring the platform."
841  } else {
842  set proc_map_entry "$proc_hier_name $proc_address_tag"
843  puts $proc_map_file "$proc_map_entry\n"
844  }
845  }
846  }
847 
848  hsi::close_hw_design [hsi::current_hw_design]
849  close $proc_map_file
850 
851 
852  Msg Info "Creating platform \[$platform_name\] with options: \{$platform_options\}"
853  set plat_create "platform create $platform_options"
854  eval $plat_create
855  platform active $platform_name
856  platform generate
857 }
858 
859 
860 proc ConfigureApps {} {
861  set apps [dict filter $globalSettings::PROPERTIES key {app:*}]
862 
863  if {[dict size $apps] == 0} {
864  Msg Info "No apps found in the configuration file"
865  return
866  }
867 
868  dict for {app_key app_config} $apps {
869  Msg Info "Found app with key: $app_key with configuration: $app_config"
870  if {[regexp {^app:(.+)$} $app_key -> app_name]} {
871  set app_name [string trim $app_name]
872  Msg Info "Configuring app: $app_name"
873  ConfigureApp $app_name $app_config
874  } else {
875  Msg Warning "Invalid app key format: $app_key. Expected format: app:<name>"
876  }
877  }
878 }
879 
880 proc ConfigureApp {app_name app_conf} {
881 
882  set create_options {
883  "platform" "domain" "sysproj" "hw"
884  "proc" "template" "os" "lang" "arch" "name"
885  }
886 
887  set conf_options {
888  "assembler-flags" "build-config" "compiler-misc" "compiler-optimization"
889  "define-compiler-symbols" "include-path" "libraries" "library-search-path"
890  "linker-misc" "linker-script" "undef-compiler-symbols"
891  }
892 
893  Msg Info "Configuring app..."
894  append app_options " -name $app_name"
895 
896  # A sysproj may have been created before, we must remove it
897  if {[catch {set sys_projs [sysproj list -dict]}]} { set sys_projs "" }
898  if {[dict exists $app_name sysproj]} {
899  set sys_proj_name [dict get $app_name sysproj]
900  if {[lsearch -exact $sys_projs "Name $sys_proj_name"] != -1} {
901  Msg Info "Removing $sys_proj_name..."
902  sysproj remove $sys_proj_name
903  }
904  } else {
905  set sys_proj_name "$app_name\_system"
906  if {[lsearch -exact $sys_projs "Name $sys_proj_name"] != -1} {
907  Msg Info "Removing $sys_proj_name..."
908  sysproj remove $sys_proj_name
909  }
910  }
911 
912  # An app may have been created before, we must remove it
913  if {[catch {set ws_apps [app list -dict]}]} { set ws_apps "" }
914  if {[lsearch -exact $ws_apps $app_name] != -1} {
915  Msg Info "app $app_name already exists, removing it..."
916  app remove $app_name
917  }
918 
919  set app_create_options [dict create]
920  set app_conf_options [dict create]
921 
922 
923  dict for {p v} $app_conf {
924  set p_lower [string tolower $p]
925 
926  if {[IsInList [string toupper $p] [VITIS_PATH_PROPERTIES] 1]} {
927  if {[IsRelativePath $v] == 1} {
928  set v "$globalSettings::repo_path/$v"
929  }
930  if {[file exists $v]} {
931  set v $globalSettings::repo_path/$v
932  } else {
933  Msg Warning "Impossible to set property $p to $v. File is missing"
934  continue
935  }
936  }
937 
938  if {[IsInList $p_lower $create_options]} {
939  Msg Info "$p_lower is in create options"
940  dict append app_create_options $p_lower $v
941  } elseif {[IsInList $p_lower $conf_options]} {
942  Msg Info "$p_lower is in conf options"
943  dict append app_conf_options $p_lower $v
944  } else {
945  Msg Warning "Unknown app option: $p_lower"
946  }
947  }
948 
949 
950  dict for {p v} $app_create_options {
951  if {[string equal $p "platform"]} {
952  Msg Info "Setting App $app_name platform to $v"
953  platform active $v
954  }
955  append app_options " -$p $v"
956  }
957 
958  if {![dict exists $app_name template]} {
959  if {[CompareVersions $globalSettings::c_v "2022 1 0"] == -1} {
960  # Check if lang is defined in create_options
961  if {[dict exists $app_create_options "lang"]} {
962  set lang [dict get $app_create_options "lang"]
963  if {[string equal -nocase $lang "C++"] || [string equal -nocase $lang "cpp"]} {
964  append app_options " -template \{Empty Application (C++)\}"
965  } else {
966  append app_options " -template \{Empty Application(C)\}"
967  }
968  } else {
969  # Default to Empty Application if lang is not specified
970  append app_options " -template \{Empty Application(C)\}"
971  }
972  } else {
973  # For newer versions, use the generic template
974  append app_options " -template \{Empty Application\}"
975  }
976  }
977 
978  Msg Info "Creating application \[$app_name\] with options: \{$app_options\}"
979  set app_create "app create $app_options"
980  eval $app_create
981  app config -name $app_name -set build-config Release
982 
983  # App config options
984  dict for {p v} $app_conf_options {
985  Msg Info "Configuring app option $p to $v"
986  app config -name $app_name -set $p $v
987  }
988 }
989 
990 
991 proc AddAppFiles {} {
992  AddHogFiles {*}[GetHogFiles -list_files {.src,.header} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path ]
993 }
994 
995 ## @brief upgrade IPs in the project and copy them from HOG_IP_PATH if defined
996 #
997 proc ManageIPs {} {
998  # set the current impl run
999  current_run -implementation [get_runs impl_1]
1000 
1001  ##############
1002  # UPGRADE IP #
1003  ##############
1004  set ips [get_ips *]
1005 
1006  Msg Info "Running report_ip_status, before upgrading and handling IPs..."
1007  report_ip_status
1008 
1009  #Pull ips from repo
1010  if {$globalSettings::HOG_IP_PATH != ""} {
1011  set ip_repo_path $globalSettings::HOG_IP_PATH
1012  Msg Info "HOG_IP_PATH is set, will pull/push synthesised IPs from/to $ip_repo_path."
1013  foreach ip $ips {
1014  HandleIP pull [get_property IP_FILE $ip] $ip_repo_path $globalSettings::repo_path [get_property IP_OUTPUT_DIR $ip]
1015  }
1016  } else {
1017  Msg Info "HOG_IP_PATH not set, will not push/pull synthesised IPs."
1018  }
1019 }
1020 
1021 proc SetGlobalVar {var {default_value HOG_NONE}} {
1022  ##nagelfar ignore
1023  if {[info exists ::$var]} {
1024  Msg Debug "Setting $var to [subst $[subst ::$var]]"
1025  ##nagelfar ignore
1026  set globalSettings::$var [subst $[subst ::$var]]
1027  } elseif {$default_value == "HOG_NONE"} {
1028  Msg Error "Mandatory variable $var was not defined. Please define it in hog.conf or in project tcl script."
1029  } else {
1030  Msg Info "Setting $var to default value: \"$default_value\""
1031  ##nagelfar ignore
1032  set globalSettings::$var $default_value
1033  }
1034 }
1035 
1036 ################################################################################################################################################################
1037 
1038 proc CreateProject {args} {
1039  # set tcl_path [file normalize "[file dirname [info script]]"]
1040  # set repo_path [file normalize $tcl_path/../..]
1041 
1042  if {[catch {package require cmdline} ERROR]} {
1043  puts "ERROR: If you are running this script on tclsh, you can fix this by installing 'tcllib'"
1044  return
1045  }
1046  set parameters {
1047  {simlib_path.arg "" "Path of simulation libs"}
1048  {verbose "If set, launch the script in verbose mode."}
1049  {xsa.arg "" "xsa for creating platforms without a defined hw."}
1050  {vivado_only "If set, and project is vivado-vitis, vitis project will not be created."}
1051  }
1052 
1053  set usage "Create Vivado/Vitis/ISE/Quartus/Libero/Diamond project.\nUsage: CreateProject \[OPTIONS\] <project> <repository path>\n Options:"
1054 
1055  if {[catch {array set options [cmdline::getoptions args $parameters $usage]}] || [llength $args] < 2 || [lindex $args 0] eq ""} {
1056  Msg Info [cmdline::usage $parameters $usage]
1057  return 1
1058  }
1059 
1060  set globalSettings::DESIGN [lindex $args 0]
1061  if {[file exists [lindex $args 1]]} {
1062  set globalSettings::repo_path [file normalize [lindex $args 1]]
1063  } else {
1064  Msg Error "The second argument, [lindex $args 1], should be the repository path."
1065  }
1066  set globalSettings::tcl_path $globalSettings::repo_path/Hog/Tcl
1067 
1068 
1069  if {$options(verbose) == 1} {
1070  variable ::DEBUG_MODE 1
1071  }
1072 
1073  if {[IsVivado]} {
1074  if {$options(simlib_path) != ""} {
1075  if {[IsRelativePath $options(simlib_path)] == 0} {
1076  set globalSettings::simlib_path "$options(simlib_path)"
1077  } else {
1078  set globalSettings::simlib_path "$globalSettings::repo_path/$options(simlib_path)"
1079  }
1080  Msg Info "Simulation library path set to $options(simlib_path)"
1081  } else {
1082  set globalSettings::simlib_path "$globalSettings::repo_path/SimulationLib"
1083  Msg Info "Simulation library path set to default $globalSettings::repo_path/SimulationLib"
1084  }
1085  }
1086 
1087  # Derived variables from now on...
1088 
1089  set build_dir_name "Projects"
1090  set globalSettings::group_name [file dirname $globalSettings::DESIGN]
1091  set globalSettings::project_name $globalSettings::DESIGN
1092  set globalSettings::pre_synth_file "pre-synthesis.tcl"
1093  set globalSettings::post_synth_file "post-synthesis.tcl"
1094  set globalSettings::pre_impl_file "pre-implementation.tcl"
1095  set globalSettings::post_impl_file "post-implementation.tcl"
1096  set globalSettings::pre_bit_file "pre-bitstream.tcl"
1097  set globalSettings::post_bit_file "post-bitstream.tcl"
1098  set globalSettings::quartus_post_module_file "quartus-post-module.tcl"
1099  set globalSettings::top_path "$globalSettings::repo_path/Top/$globalSettings::DESIGN"
1100  set globalSettings::list_path "$globalSettings::top_path/list"
1101  set globalSettings::build_dir "$globalSettings::repo_path/$build_dir_name/$globalSettings::DESIGN"
1102  set globalSettings::DESIGN [file tail $globalSettings::DESIGN]
1103  set globalSettings::top_name [file tail $globalSettings::DESIGN]
1104  set globalSettings::top_name [file rootname $globalSettings::top_name]
1105  set globalSettings::synth_top_module "top_$globalSettings::top_name"
1106  set globalSettings::user_ip_repo ""
1107 
1108  set globalSettings::pre_synth [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_synth_file"]
1109  set globalSettings::post_synth [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_synth_file"]
1110  set globalSettings::pre_impl [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_impl_file"]
1111  set globalSettings::post_impl [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_impl_file"]
1112  set globalSettings::pre_bit [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_bit_file"]
1113  set globalSettings::post_bit [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_bit_file"]
1114  set globalSettings::quartus_post_module [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::quartus_post_module_file"]
1115  set globalSettings::LIBERO_MANDATORY_VARIABLES {"FAMILY" "PACKAGE" "DIE" }
1116 
1117  set proj_dir [file normalize $globalSettings::repo_path/Top/$globalSettings::project_name]
1118  Msg Debug "Calling GetConfFiles with proj_dir=$proj_dir (project_name=$globalSettings::project_name)"
1119  lassign [GetConfFiles $proj_dir] conf_file sim_file pre_file post_file
1120 
1121  set user_repo 0
1122  if {[file exists $conf_file]} {
1123  Msg Info "Parsing configuration file $conf_file..."
1124  SetGlobalVar PROPERTIES [ReadConf $conf_file]
1125 
1126  # Checking Vivado/Vitis/Quartus/ISE/Libero version
1127  set actual_version [GetIDEVersion]
1128  lassign [GetIDEFromConf $conf_file] ide conf_version
1129  if {([string tolower $ide] eq "vivado_vitis_classic") && ($options(vivado_only) != 1)} {
1130  puts "Vitis classic detected, setting globalSettings::vitis_classic to 1"
1131  set globalSettings::vitis_classic 1
1132  } else {
1133  set globalSettings::vitis_classic 0
1134  }
1135 
1136  if {$conf_version != "0.0.0"} {
1137  set globalSettings::a_v [split $actual_version "."]
1138  set globalSettings::c_v [split $conf_version "."]
1139 
1140  if {[llength $globalSettings::a_v] < 2} {
1141  Msg Error "Couldn't parse IDE version: $actual_version."
1142  } elseif {[llength $globalSettings::a_v] == 2} {
1143  lappend globalSettings::a_v 0
1144  }
1145  if {[llength $globalSettings::c_v] < 2} {
1146  Msg Error "Wrong version format in hog.conf: $conf_version."
1147  } elseif {[llength $globalSettings::c_v] == 2} {
1148  lappend globalSettings::c_v 0
1149  }
1150 
1151  set comp [CompareVersions $globalSettings::a_v $globalSettings::c_v]
1152  if {$comp == 0} {
1153  Msg Info "Project version and $ide version match: $conf_version."
1154  } elseif {$comp == 1} {
1155  Msg CriticalWarning "The $ide version in use is $actual_version, that is newer than $conf_version, as specified in the first line of $conf_file.\n\
1156  If you want update this project to version $actual_version, please update the configuration file."
1157  } else {
1158  # tclint-disable-next-line line-length
1159  Msg Error "The $ide version in use is $actual_version, that is older than $conf_version as specified in $conf_file. The project will not be created.\nIf you absolutely want to create this project that was meant for version $conf_version with $ide version $actual_version, you can change the version from the first line of $conf_file.\nThis is HIGHLY discouraged as there could be unrecognised properties in the configuration file and IPs created with a newer $ide version cannot be downgraded."
1160  }
1161  } else {
1162  Msg CriticalWarning "No version found in the first line of $conf_file. \
1163  It is HIGHLY recommended to replace the first line of $conf_file with: \#$ide $actual_version"
1164  }
1165 
1166  if {$globalSettings::vitis_classic == 1} {
1167  if {[CompareVersions $globalSettings::a_v "2020 2 0"] == -1 || [CompareVersions $globalSettings::c_v "2020 2 0"] == -1} {
1168  Msg Error "Vitis flow is not supported for versions < 2020.2. Please use Vitis 2020.2 or newer." }
1169  }
1170 
1171 
1172  if {[dict exists $globalSettings::PROPERTIES main]} {
1173  set main [dict get $globalSettings::PROPERTIES main]
1174  dict for {p v} $main {
1175  # notice the dollar in front of p: creates new variables and fill them with the value
1176  Msg Info "Main property $p set to $v"
1177  ##nagelfar ignore
1178  set ::$p $v
1179  }
1180  } else {
1181  Msg Error "No main section found in $conf_file, make sure it has a section called \[main\] containing the mandatory properties."
1182  }
1183  } else {
1184  Msg Error "$conf_file was not found in your project directory, please create one."
1185  }
1186 
1187 
1188  if {[IsXilinx] || [IsQuartus]} {
1189  SetGlobalVar PART
1190  }
1191  #Family is needed in quartus and libero only
1192  if {[IsQuartus] || [IsLibero]} {
1193  #Quartus only
1194  SetGlobalVar FAMILY
1195  if {[IsLibero]} {
1196  SetGlobalVar DIE
1197  SetGlobalVar PACKAGE
1198  }
1199  }
1200 
1201  if {[IsDiamond]} {
1202  SetGlobalVar DEVICE
1203  SetGlobalVar SYNTHESIS_TOOL "lse"
1204  }
1205 
1206  if {[IsVivado]} {
1207  SetGlobalVar TARGET_SIMULATOR "XSim"
1208  }
1209 
1210  if {[info exists env(HOG_EXTERNAL_PATH)]} {
1211  set globalSettings::HOG_EXTERNAL_PATH $env(HOG_EXTERNAL_PATH)
1212  } else {
1213  set globalSettings::HOG_EXTERNAL_PATH ""
1214  }
1215 
1216  set user_hog_file "$globalSettings::repo_path/Top/hog.tcl"
1217  if {[file exists $user_hog_file]} {
1218  Msg Info "Sourcing user hog.tcl file..."
1219  source $user_hog_file
1220  }
1221 
1222  if {[file exists $pre_file]} {
1223  Msg Info "Found pre-creation Tcl script $pre_file, executing it..."
1224  source $pre_file
1225  }
1226 
1227  if {[info exists env(HOG_IP_PATH)]} {
1228  set globalSettings::HOG_IP_PATH $env(HOG_IP_PATH)
1229  } else {
1230  set globalSettings::HOG_IP_PATH ""
1231  }
1232 
1233  InitProject
1234 
1235  if {[IsVitisClassic]} {
1236  if {$options(xsa) != ""} {
1237  Msg Info "Configuring platforms with xsa: $options(xsa)"
1238  ConfigurePlatforms "$options(xsa)"
1239  } else {
1241  }
1243  AddAppFiles
1244  return
1245  }
1246 
1251 
1252 
1253  if {[IsVivado]} {
1254  # Use HandleIP to pull IPs from HOG_IP_PATH if specified
1255  ManageIPs
1256  }
1257 
1258  if {[IsQuartus]} {
1259  set fileName_old [file normalize "./hogTmp/.hogQsys.md5"]
1260  set fileDir [file normalize "$globalSettings::build_dir/.hog/"]
1261  file mkdir $fileDir
1262  set fileName_new [file normalize "$fileDir/.hogQsys.md5"]
1263  if {[file exists $fileName_new]} {
1264  file delete $fileName_new
1265  }
1266  if {[file exists $fileName_old]} {
1267  file rename -force $fileName_old $fileName_new
1268  file delete -force -- "./hogTmp"
1269  }
1270  }
1271 
1272  if {[file exists $post_file]} {
1273  Msg Info "Found post-creation Tcl script $post_file, executing it..."
1274  source $post_file
1275  if {[IsLibero]} {
1276  # Regenerate the hierarchy in case a new file has been added
1277  build_design_hierarchy
1278  }
1279  }
1280 
1281  # Check extra IPs
1282  # Get project libraries and properties from list files
1283  lassign [GetHogFiles \
1284  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
1285  -list_files ".src,.ext" \
1286  "$globalSettings::repo_path/Top/$globalSettings::project_name/list/" \
1287  $globalSettings::repo_path] \
1288  listLibraries listProperties listSrcSets
1289  # Get project constraints and properties from list files
1290  lassign [GetHogFiles \
1291  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
1292  -list_files ".con" \
1293  "$globalSettings::repo_path/Top/$globalSettings::project_name/list/" \
1294  $globalSettings::repo_path] \
1295  listConstraints listConProperties listConSets
1296 
1297  lassign [GetHogFiles \
1298  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
1299  -list_files ".sim" \
1300  "$globalSettings::repo_path/Top/$globalSettings::project_name/list/" \
1301  $globalSettings::repo_path] \
1302  listSimLibraries listSimProperties listSimSets
1303 
1304  set old_path [pwd]
1305  cd $globalSettings::build_dir
1306  CheckExtraFiles $listLibraries $listConstraints $listSimLibraries
1307  cd $old_path
1308 
1309  if {[IsXilinx]} {
1310  set old_path [pwd]
1311  cd $globalSettings::repo_path
1312  set flavour [GetProjectFlavour $globalSettings::DESIGN]
1313  # Getting all the versions and SHAs of the repository
1314  lassign [GetRepoVersions \
1315  [file normalize $globalSettings::repo_path/Top/$globalSettings::project_name] \
1316  $globalSettings::repo_path \
1317  $globalSettings::HOG_EXTERNAL_PATH \
1318  ] commit version hog_hash hog_ver top_hash top_ver libs hashes vers cons_ver cons_hash ext_names ext_hashes \
1319  xml_hash xml_ver user_ip_repos user_ip_hashes user_ip_vers
1320 
1321  set this_commit [GetSHA]
1322 
1323  if {$commit == 0} {
1324  set commit $this_commit
1325  }
1326 
1327  if {$xml_hash != ""} {
1328  set use_ipbus 1
1329  } else {
1330  set use_ipbus 0
1331  }
1332 
1333 
1334  lassign [GetDateAndTime $commit] date timee
1335  WriteGenerics "create" \
1336  $globalSettings::repo_path \
1337  $globalSettings::project_name \
1338  $date $timee $commit $version \
1339  $top_hash $top_ver $hog_hash $hog_ver \
1340  $cons_ver $cons_hash $libs $vers $hashes \
1341  $ext_names $ext_hashes $user_ip_repos $user_ip_vers \
1342  $user_ip_hashes $flavour $xml_ver $xml_hash
1343  cd $old_path
1344  }
1345 
1346  if {[IsLibero]} {
1347  save_project
1348  }
1349 
1350  if {[IsDiamond]} {
1351  prj_project save
1352  }
1353 
1354 
1355  if {($globalSettings::vitis_classic == 1)} {
1356  # Presynth hw platform, let's keep it in the build directory
1357  write_hw_platform -fixed -force -file [file normalize "$globalSettings::build_dir/$globalSettings::DESIGN-presynth.xsa"]
1358 
1359  # Launch xsct to build the project
1360  if {$options(xsa) == ""} {
1361  set xsa_opt ""
1362  } else {
1363  if {[IsRelativePath $options(xsa)] == 0} {
1364  set xsa_opt "-xsa $options(xsa)"
1365  } else {
1366  set xsa_opt "-xsa $globalSettings::repo_path/$options(xsa)"
1367  }
1368  }
1369 
1370  set xsct_cmd "xsct $globalSettings::tcl_path/launch.tcl C $xsa_opt -vitis_only $globalSettings::project_name"
1371  Msg Info "Running Vitis Classic project creation script with command: $xsct_cmd"
1372  set ret [catch {exec -ignorestderr {*}$xsct_cmd >@ stdout} result]
1373  if {$ret != 0} {
1374  Msg Error "xsct (vitis classic) returned an error state."
1375  }
1376  }
1377 
1378 
1379  Msg Info "Project $globalSettings::project_name created successfully in [Relative $globalSettings::repo_path $globalSettings::build_dir]."
1380 }