Hog v9.61.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 pre_synth
69  variable post_synth
70  variable pre_impl
71  variable post_impl
72  variable pre_bit
73  variable post_bit
74  variable quartus_post_module
75 }
76 
77 ################# FUNCTIONS ################################
78 proc InitProject {} {
79  if {[IsXilinx]} {
80  if {[IsVivado]} {
81  # Suppress unnecessary warnings
82  # tclint-disable-next-line line-length
83  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..*"}
84  set_msg_config -suppress -regexp -string {".*File '.*.xci' referenced by design '.*' could not be found..*"}
85 
86  # File inside .bd
87  set_msg_config -suppress -id {IP_Flow 19-3664}
88  # This is due to simulations in project with NoC
89  # tclint-disable-next-line line-length
90  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} }
91  }
92  # Create project
93  create_project -force [file tail $globalSettings::DESIGN] $globalSettings::build_dir -part $globalSettings::PART
94  file mkdir "$globalSettings::build_dir/[file tail $globalSettings::DESIGN].gen/sources_1"
95  if {[IsVersal $globalSettings::PART]} {
96  Msg Info "This project uses a Versal device."
97  }
98 
99  ## Set project properties
100  set obj [get_projects [file tail $globalSettings::DESIGN]]
101  set_property "target_language" "VHDL" $obj
102 
103  if {[IsVivado]} {
104  set_property "simulator_language" "Mixed" $obj
105  foreach simulator [GetSimulators] {
106  set_property "compxlib.${simulator}_compiled_library_dir" $globalSettings::simlib_path $obj
107  }
108  set_property "default_lib" "xil_defaultlib" $obj
109  ## Enable VHDL 2008
110  set_param project.enableVHDL2008 1
111  set_property "enable_vhdl_2008" 1 $obj
112  ## Enable Automatic compile order mode, otherwise we cannot find the right top module...
113  set_property source_mgmt_mode All [current_project]
114  # Set PART Immediately
115  Msg Debug "Setting PART = $globalSettings::PART"
116  set_property PART $globalSettings::PART [current_project]
117  }
118 
120  } elseif {[IsQuartus]} {
121  package require ::quartus::project
122  #QUARTUS_ONLY
123  if {[string equal $globalSettings::FAMILY "quartus_only"]} {
124  Msg Error "You must specify a device Family for Quartus"
125  } else {
126  file mkdir $globalSettings::build_dir
127  cd $globalSettings::build_dir
128  if {[is_project_open]} {
129  project_close
130  }
131 
132  file delete {*}[glob -nocomplain $globalSettings::DESIGN.q*]
133 
134  project_new -family $globalSettings::FAMILY -overwrite -part $globalSettings::PART $globalSettings::DESIGN
135  set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
136 
138  }
139  } elseif {[IsLibero]} {
140  if {[file exists $globalSettings::build_dir]} {
141  file delete -force $globalSettings::build_dir
142  }
143  new_project -location $globalSettings::build_dir \
144  -name [file tail $globalSettings::DESIGN] \
145  -die $globalSettings::DIE \
146  -package $globalSettings::PACKAGE \
147  -family $globalSettings::FAMILY \
148  -hdl VHDL
149  } elseif {[IsDiamond]} {
150  if {[file exists $globalSettings::build_dir]} {
151  file delete -force $globalSettings::build_dir
152  }
153  set old_dir [pwd]
154  file mkdir $globalSettings::build_dir
155  cd $globalSettings::build_dir
156  prj_project new -name [file tail $globalSettings::DESIGN] -dev $globalSettings::DEVICE -synthesis $globalSettings::SYNTHESIS_TOOL
157  cd $old_dir
159  } else {
160  puts "Creating project for $globalSettings::DESIGN part $globalSettings::PART"
161  puts "Configuring project settings:"
162  puts " - simulator_language: Mixed"
163  puts " - target_language: VHDL"
164  puts " - simulator: QuestaSim"
165  puts "Adding IP directory \"$globalSettings::user_ip_repo\" to the project "
166  }
167 }
168 
169 proc AddProjectFiles {} {
170  if {[IsXilinx]} {
171  #VIVADO_ONLY
172  ## Create fileset src
173  if {[string equal [get_filesets -quiet sources_1] ""]} {
174  create_fileset -srcset sources_1
175  }
176  set sources "sources_1"
177  } else {
178  set sources 0
179  }
180 
181 
182  ###############
183  # CONSTRAINTS #
184  ###############
185  if {[IsXilinx]} {
186  #VIVADO_ONLY
187  # Create 'constrs_1' fileset (if not found)
188  if {[string equal [get_filesets -quiet constrs_1] ""]} {
189  create_fileset -constrset constrs_1
190  }
191 
192  # Set 'constrs_1' fileset object
193  set constraints [get_filesets constrs_1]
194  }
195 
196  ##############
197  # READ FILES #
198  ##############
199 
200  if {[file isdirectory $globalSettings::list_path]} {
201  set list_files [glob -directory $globalSettings::list_path "*"]
202  } else {
203  Msg Error "No list directory found at $globalSettings::list_path"
204  }
205 
206  if {[IsISE]} {
207  source $globalSettings::tcl_path/utils/cmdline.tcl
208  }
209 
210  # Add first .src, .sim, and .ext list files
211  AddHogFiles {*}[GetHogFiles -list_files {.src,.sim,.ext} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path]
212 
213  ## Set synthesis TOP
214  SetTopProperty $globalSettings::synth_top_module $sources
215 
216  # Libero needs the top files to be set before adding the constraints
217  AddHogFiles {*}[GetHogFiles -list_files {.con} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path]
218  ## Set simulation Properties
219 
220  ## Libero Properties must be set after that root has been defined
221  if {[IsLibero]} {
223  }
224 }
225 
226 
227 ## @brief Set Vivado Report strategy for implementation
228 #
229 # @param[in] obj the project object
230 #
231 proc CreateReportStrategy {obj} {
232  #TODO: Add ReportStrategy for Quartus/Libero and Diamond
233 
234  if {[IsVivado]} {
235  ## Vivado Report Strategy
236  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
237  # No report strategy needed
238  Msg Info "No report strategy needed for implementation"
239  } else {
240  # Report strategy needed since version 2017.3
241  set_property set_report_strategy_name 1 $obj
242  set_property report_strategy {Vivado Implementation Default Reports} $obj
243  set_property set_report_strategy_name 0 $obj
244 
245  set reports [get_report_configs -of_objects $obj]
246  # Create 'impl_1_place_report_utilization_0' report (if not found)
247  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] ""]} {
248  create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1
249  }
250  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0]
251  if {$obj != ""} {
252 
253  }
254 
255  # Create 'impl_1_route_report_drc_0' report (if not found)
256  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] ""]} {
257  create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1
258  }
259  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0]
260  if {$obj != ""} {
261 
262  }
263 
264  # Create 'impl_1_route_report_power_0' report (if not found)
265  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] ""]} {
266  create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1
267  }
268  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0]
269  if {$obj != ""} {
270 
271  }
272 
273  # Create 'impl_1_route_report_timing_summary' report (if not found)
274  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary] ""]} {
275  create_report_config -report_name impl_1_route_report_timing_summary -report_type report_timing_summary:1.0 -steps route_design -runs impl_1
276  }
277  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary]
278  if {$obj != ""} {
279  Msg Info "Report timing created successfully"
280  }
281 
282  # Create 'impl_1_route_report_utilization' report (if not found)
283  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization] ""]} {
284  create_report_config -report_name impl_1_route_report_utilization -report_type report_utilization:1.0 -steps route_design -runs impl_1
285  }
286  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization]
287  if {$obj != ""} {
288  Msg Info "Report utilization created successfully"
289  }
290 
291 
292  # Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found)
293  if {[string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] ""]} {
294  create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 \
295  -report_type report_timing_summary:1.0 \
296  -steps post_route_phys_opt_design -runs impl_1
297  }
298  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0]
299  if {$obj != ""} {
300  set_property -name "options.max_paths" -value "10" -objects $obj
301  set_property -name "options.warn_on_violation" -value "1" -objects $obj
302  }
303  }
304  } else {
305  Msg Info "Won't create any report strategy, not in Vivado"
306  }
307 }
308 
309 
310 ## @brief configure synthesis.
311 #
312 # The method uses the content of globalSettings::SYNTH_FLOW and globalSettings::SYNTH_STRATEGY to set the implementation strategy and flow.
313 # The function also sets Hog specific pre and post synthesis scripts
314 #
315 proc ConfigureSynthesis {} {
316  if {[IsXilinx]} {
317  #VIVADO ONLY
318  ## Create 'synthesis ' run (if not found)
319  if {[string equal [get_runs -quiet synth_1] ""]} {
320  create_run -name synth_1 -part $globalSettings::PART -constrset constrs_1
321  } else {
322 
323  }
324 
325  set obj [get_runs synth_1]
326  set_property "part" $globalSettings::PART $obj
327  }
328 
329  ## set pre synthesis script
330  if {$globalSettings::pre_synth_file ne ""} {
331  if {[IsXilinx]} {
332  #Vivado Only
333  if {[IsVivado]} {
334  if {[get_filesets -quiet utils_1] != ""} {
335  AddFile $globalSettings::pre_synth [get_filesets -quiet utils_1]
336  }
337  set_property STEPS.SYNTH_DESIGN.TCL.PRE $globalSettings::pre_synth $obj
338  }
339  } elseif {[IsQuartus]} {
340  #QUARTUS only
341  set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_synth
342  } elseif {[IsLibero]} {
343  configure_tool -name {SYNTHESIZE} -params SYNPLIFY_TCL_FILE:$globalSettings::pre_synth
344  } elseif {[IsDiamond]} {
345  prj_impl pre_script "syn" $globalSettings::pre_synth
346  }
347 
348  Msg Debug "Setting $globalSettings::pre_synth to be run before synthesis"
349  }
350 
351  ## set post synthesis script
352  if {$globalSettings::post_synth_file ne ""} {
353  if {[IsXilinx]} {
354  #Vivado Only
355  if {[IsVivado]} {
356  if {[get_filesets -quiet utils_1] != ""} {
357  AddFile $globalSettings::post_synth [get_filesets -quiet utils_1]
358  }
359  set_property STEPS.SYNTH_DESIGN.TCL.POST $globalSettings::post_synth $obj
360  }
361  } elseif {[IsQuartus]} {
362  #QUARTUS only
363  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
364  } elseif {[IsDiamond]} {
365  prj_impl post_script "syn" $globalSettings::post_synth
366  }
367  Msg Debug "Setting $globalSettings::post_synth to be run after synthesis"
368  }
369 
370 
371  if {[IsXilinx]} {
372  #VIVADO ONLY
373  ## set the current synth run
374  current_run -synthesis $obj
375 
376  ## Report Strategy
377  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
378  # No report strategy needed
379  Msg Debug "No report strategy needed for synthesis"
380  } else {
381  # Report strategy needed since version 2017.3
382  set_property set_report_strategy_name 1 $obj
383  set_property report_strategy {Vivado Synthesis Default Reports} $obj
384  set_property set_report_strategy_name 0 $obj
385  # Create 'synth_1_synth_report_utilization_0' report (if not found)
386  if {[string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] ""]} {
387  create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1
388  }
389  set reports [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]
390  }
391  } elseif {[IsQuartus]} {
392  #QUARTUS only
393  #TO BE DONE
394  } elseif {[IsLibero]} {
395  #TODO: LIBERO
396  } elseif {[IsDiamond]} {
397  #TODO: Diamond
398  } else {
399  Msg info "Reporting strategy for synthesis"
400  }
401 }
402 
403 ## @brief configure implementation.
404 #
405 # The configuration is based on the content of globalSettings::IMPL_FLOW and globalSettings::IMPL_STRATEGY
406 # The function also sets Hog specific pre- and- post implementation and, pre- and post- implementation scripts
407 #
408 proc ConfigureImplementation {} {
409  set obj ""
410  if {[IsXilinx]} {
411  # Create 'impl_1' run (if not found)
412  if {[string equal [get_runs -quiet impl_1] ""]} {
413  create_run -name impl_1 -part $globalSettings::PART -constrset constrs_1 -parent_run synth_1
414  }
415 
416  set obj [get_runs impl_1]
417  set_property "part" $globalSettings::PART $obj
418 
419  set_property "steps.[BinaryStepName $globalSettings::PART].args.readback_file" "0" $obj
420  set_property "steps.[BinaryStepName $globalSettings::PART].args.verbose" "0" $obj
421  } elseif {[IsQuartus]} {
422  #QUARTUS only
423  set obj ""
424  }
425 
426 
427  ## set pre implementation script
428  if {$globalSettings::pre_impl_file ne ""} {
429  if {[IsXilinx]} {
430  #Vivado Only
431  if {[IsVivado]} {
432  if {[get_filesets -quiet utils_1] != ""} {
433  AddFile $globalSettings::pre_impl [get_filesets -quiet utils_1]
434  }
435  set_property STEPS.INIT_DESIGN.TCL.POST $globalSettings::pre_impl $obj
436  }
437  } elseif {[IsQuartus]} {
438  #QUARTUS only
439  #set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_impl
440  } elseif {[IsDiamond]} {
441  prj_impl pre_script "par" $globalSettings::pre_impl
442  }
443  Msg Debug "Setting $globalSettings::pre_impl to be run after implementation"
444  }
445 
446 
447  ## set post routing script
448  if {$globalSettings::post_impl_file ne ""} {
449  if {[IsXilinx]} {
450  #Vivado Only
451  if {[IsVivado]} {
452  if {[get_filesets -quiet utils_1] != ""} {
453  AddFile $globalSettings::post_impl [get_filesets -quiet utils_1]
454  }
455  set_property STEPS.ROUTE_DESIGN.TCL.POST $globalSettings::post_impl $obj
456  }
457  } elseif {[IsQuartus]} {
458  #QUARTUS only
459  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
460  } elseif {[IsDiamond]} {
461  prj_impl post_script "par" $globalSettings::post_impl
462  }
463  Msg Debug "Setting $globalSettings::post_impl to be run after implementation"
464  }
465 
466  ## set pre write bitstream script
467  if {$globalSettings::pre_bit_file ne ""} {
468  if {[IsXilinx]} {
469  #Vivado Only
470  if {[IsVivado]} {
471  if {[get_filesets -quiet utils_1] != ""} {
472  AddFile $globalSettings::pre_bit [get_filesets -quiet utils_1]
473  }
474  set_property STEPS.[BinaryStepName $globalSettings::PART].TCL.PRE $globalSettings::pre_bit $obj
475  }
476  } elseif {[IsQuartus]} {
477  #QUARTUS only
478  #set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_bit
479  } elseif {[IsDiamond]} {
480  prj_impl pre_script "export" $globalSettings::pre_bit
481  }
482  Msg Debug "Setting $globalSettings::pre_bit to be run after bitfile generation"
483  }
484 
485  ## set post write bitstream script
486  if {$globalSettings::post_bit_file ne ""} {
487  if {[IsXilinx]} {
488  #Vivado Only
489  if {[IsVivado]} {
490  if {[get_filesets -quiet utils_1] != ""} {
491  AddFile $globalSettings::post_bit [get_filesets -quiet utils_1]
492  }
493  set_property STEPS.[BinaryStepName $globalSettings::PART].TCL.POST $globalSettings::post_bit $obj
494  }
495  } elseif {[IsQuartus]} {
496  #QUARTUS only
497  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
498  } elseif {[IsDiamond]} {
499  prj_impl post_script "export" $globalSettings::post_bit
500  }
501  Msg Debug "Setting $globalSettings::post_bit to be run after bitfile generation"
502  }
503 
505 }
506 
507 
508 ## @brief configure simulation
509 #
510 proc ConfigureSimulation {} {
511  set simsets_dict [GetSimSets "$globalSettings::group_name/$globalSettings::DESIGN" $globalSettings::repo_path]
512 
513  if {[IsXilinx]} {
514  ##############
515  # SIMULATION #
516  ##############
517  Msg Debug "Setting load_glbl parameter to true for every fileset..."
518  foreach simset [get_filesets -quiet] {
519  if {[get_property FILESET_TYPE $simset] != "SimulationSrcs"} {
520  continue
521  }
522  if {[IsVivado]} {
523  set_property -name {xsim.elaborate.load_glbl} -value {true} -objects [get_filesets $simset]
524  }
525  # Setting Simulation Properties
526  set sim_dict [DictGet $simsets_dict $simset]
527  set sim_props [DictGet $sim_dict "properties"]
528 
529  if {$sim_props != ""} {
530  Msg Info "Setting properties for simulation set: $simset..."
531  dict for {prop_name prop_val} $sim_props {
532  set prop_name [string toupper $prop_name]
533  if {$prop_name == "ACTIVE" && $prop_val == 1} {
534  Msg Info "Setting $simset as active simulation set..."
535  current_fileset -simset [get_filesets $simset]
536  } else {
537  Msg Debug "Setting $prop_name = $prop_val"
538  if {[IsInList [string toupper $prop_name] [VIVADO_PATH_PROPERTIES] 1]} {
539  # Check that the file exists before setting these properties
540  if {[file exists $globalSettings::repo_path/$prop_val]} {
541  set_property $prop_name $globalSettings::repo_path/$prop_val [get_filesets $simset]
542  } else {
543  Msg Warning "Impossible to set property $prop_name to $prop_val. File is missing"
544  }
545  } else {
546  set_property $prop_name $prop_val [get_filesets $simset]
547  }
548  }
549  }
550  }
551  }
552  }
553 }
554 
555 ## @brief uses the content of globalSettings::PROPERTIES to set additional project properties
556 #
557 proc ConfigureProperties {} {
558  set cur_dir [pwd]
559  cd $globalSettings::repo_path
560  if {[IsXilinx]} {
561  set user_repo "0"
562  # Setting Main Properties
563  if {[info exists globalSettings::PROPERTIES]} {
564  if {[dict exists $globalSettings::PROPERTIES main]} {
565  Msg Info "Setting project-wide properties..."
566  set proj_props [dict get $globalSettings::PROPERTIES main]
567  dict for {prop_name prop_val} $proj_props {
568  if {[string tolower $prop_name] != "ip_repo_paths"} {
569  if {[string tolower $prop_name] != "part"} {
570  # Part is already set
571  Msg Debug "Setting $prop_name = $prop_val"
572  set_property $prop_name $prop_val [current_project]
573  }
574  } else {
575  set ip_repo_list [regsub -all {\s+} $prop_val " $globalSettings::repo_path/"]
576  set ip_repo_list $globalSettings::repo_path/$ip_repo_list
577  set user_repo "1"
578  Msg Info "Setting $ip_repo_list as user IP repository..."
579  if {[IsISE]} {
580  set_property ip_repo_paths "$ip_repo_list" [current_fileset]
581  } else {
582  set_property ip_repo_paths "$ip_repo_list" [current_project]
583  }
584  update_ip_catalog
585  }
586  }
587  }
588  # Setting Run Properties
589  foreach run [get_runs -quiet] {
590  if {[dict exists $globalSettings::PROPERTIES $run]} {
591  Msg Info "Setting properties for run: $run..."
592  set run_props [dict get $globalSettings::PROPERTIES $run]
593  #set_property -dict $run_props $run
594  set stragety_str "STRATEGY strategy Strategy"
595  Msg Debug "Setting Strategy and Flow for run $run (if specified in hog.conf)"
596  foreach s $stragety_str {
597  if {[dict exists $run_props $s]} {
598  set prop [dict get $run_props $s]
599  set_property $s $prop $run
600  set run_props [dict remove $run_props $s]
601  Msg Warning "A strategy for run $run has been defined inside hog.conf. This prevents Hog to compare the project properties. \
602  Please regenerate your hog.conf file using the dedicated Hog button."
603  Msg Info "Setting $s = $prop"
604  }
605  }
606 
607  dict for {prop_name prop_val} $run_props {
608  Msg Debug "Setting $prop_name = $prop_val"
609  if {[string trim $prop_val] == ""} {
610  Msg Warning "Property $prop_name has empty value. Skipping..."
611  continue
612  }
613  if {[IsInList [string toupper $prop_name] [VIVADO_PATH_PROPERTIES] 1]} {
614  # Check that the file exists before setting these properties
615  set utility_file $globalSettings::repo_path/$prop_val
616  if {[file exists $utility_file]} {
617  lassign [GetHogFiles -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path] lib prop dummy
618  foreach {l f} $lib {
619  foreach ff $f {
620  lappend hog_files $ff
621  }
622  }
623  if {[lsearch $hog_files $utility_file] < 0} {
624  Msg CriticalWarning "The file: $utility_file is set as a property in hog.conf, \
625  but is not added to the project in any list file. Hog cannot track it."
626  } else {
627  #Add file tu utils_1 to avoid warning
628  AddFile $globalSettings::repo_path/$prop_val [get_filesets -quiet utils_1]
629  }
630  set_property $prop_name $utility_file $run
631  } else {
632  Msg Warning "Impossible to set property $prop_name to $prop_val. File is missing"
633  }
634  } else {
635  set_property $prop_name $prop_val $run
636  }
637  }
638  }
639  }
640  }
641  } elseif {[IsQuartus]} {
642  #QUARTUS only
643  #TO BE DONE
644  } elseif {[IsLibero]} {
645  # Setting Properties
646  if {[info exists globalSettings::PROPERTIES]} {
647  # Device Properties
648  if {[dict exists $globalSettings::PROPERTIES main]} {
649  Msg Info "Setting device properties..."
650  set dev_props [dict get $globalSettings::PROPERTIES main]
651  dict for {prop_name prop_val} $dev_props {
652  if {!([string toupper $prop_name] in $globalSettings::LIBERO_MANDATORY_VARIABLES)} {
653  Msg Debug "Setting $prop_name = $prop_val"
654  set_device -[string tolower $prop_name] $prop_val
655  }
656  }
657  }
658  # Project Properties
659  if {[dict exists $globalSettings::PROPERTIES project]} {
660  Msg Info "Setting project-wide properties..."
661  set dev_props [dict get $globalSettings::PROPERTIES project]
662  dict for {prop_name prop_val} $dev_props {
663  Msg Debug "Setting $prop_name = $prop_val"
664  project_settings -[string tolower $prop_name] $prop_val
665  }
666  }
667  # Synthesis Properties
668  if {[dict exists $globalSettings::PROPERTIES synth]} {
669  Msg Info "Setting Synthesis properties..."
670  set synth_props [dict get $globalSettings::PROPERTIES synth]
671  dict for {prop_name prop_val} $synth_props {
672  Msg Debug "Setting $prop_name = $prop_val"
673  configure_tool -name {SYNTHESIZE} -params "[string toupper $prop_name]:$prop_val"
674  }
675  }
676  # Implementation Properties
677  if {[dict exists $globalSettings::PROPERTIES impl]} {
678  Msg Info "Setting Implementation properties..."
679  set impl_props [dict get $globalSettings::PROPERTIES impl]
680  dict for {prop_name prop_val} $impl_props {
681  Msg Debug "Setting $prop_name = $prop_val"
682  configure_tool -name {PLACEROUTE} -params "[string toupper $prop_name]:$prop_val"
683  }
684  }
685 
686  # Bitstream Properties
687  if {[dict exists $globalSettings::PROPERTIES bitstream]} {
688  Msg Info "Setting Bitstream properties..."
689  set impl_props [dict get $globalSettings::PROPERTIES impl]
690  dict for {prop_name prop_val} $impl_props {
691  Msg Debug "Setting $prop_name = $prop_val"
692  configure_tool -name {GENERATEPROGRAMMINGFILE} -params "[string toupper $prop_name]:$prop_val"
693  }
694  }
695  # Configure VERIFYTIMING tool to generate a txt file report
696  configure_tool -name {VERIFYTIMING} -params {FORMAT:TEXT}
697  }
698  } elseif {[IsDiamond]} {
699  if {[info exists globalSettings::PROPERTIES]} {
700  # Project (main) Properties
701  if {[dict exists $globalSettings::PROPERTIES main]} {
702  Msg Info "Setting project-wide properties..."
703  set dev_props [dict get $globalSettings::PROPERTIES main]
704  dict for {prop_name prop_val} $dev_props {
705  # Device is already set
706  if {[string toupper $prop_name] != "DEVICE"} {
707  Msg Debug "Setting $prop_name = $prop_val"
708  prj_project option $prop_name $prop_val
709  }
710  }
711  }
712  # Implementation properties
713  if {[dict exists $globalSettings::PROPERTIES impl]} {
714  Msg Info "Setting Implementation properties..."
715  set dev_props [dict get $globalSettings::PROPERTIES impl]
716  dict for {prop_name prop_val} $dev_props {
717  # Device is already set
718  Msg Debug "Setting $prop_name = $prop_val"
719  prj_impl option $prop_name $prop_val
720  }
721  }
722  }
723  } else {
724  Msg info "Configuring Properties"
725  }
726  cd $cur_dir
727 }
728 
729 ## @brief upgrade IPs in the project and copy them from HOG_IP_PATH if defined
730 #
731 proc ManageIPs {} {
732  # set the current impl run
733  current_run -implementation [get_runs impl_1]
734 
735  ##############
736  # UPGRADE IP #
737  ##############
738  set ips [get_ips *]
739 
740  Msg Info "Running report_ip_status, before upgrading and handling IPs..."
741  report_ip_status
742 
743  #Pull ips from repo
744  if {$globalSettings::HOG_IP_PATH != ""} {
745  set ip_repo_path $globalSettings::HOG_IP_PATH
746  Msg Info "HOG_IP_PATH is set, will pull/push synthesised IPs from/to $ip_repo_path."
747  foreach ip $ips {
748  HandleIP pull [get_property IP_FILE $ip] $ip_repo_path $globalSettings::repo_path [get_property IP_OUTPUT_DIR $ip]
749  }
750  } else {
751  Msg Info "HOG_IP_PATH not set, will not push/pull synthesised IPs."
752  }
753 }
754 
755 proc SetGlobalVar {var {default_value HOG_NONE}} {
756  ##nagelfar ignore
757  if {[info exists ::$var]} {
758  Msg Debug "Setting $var to [subst $[subst ::$var]]"
759  ##nagelfar ignore
760  set globalSettings::$var [subst $[subst ::$var]]
761  } elseif {$default_value == "HOG_NONE"} {
762  Msg Error "Mandatory variable $var was not defined. Please define it in hog.conf or in project tcl script."
763  } else {
764  Msg Info "Setting $var to default value: \"$default_value\""
765  ##nagelfar ignore
766  set globalSettings::$var $default_value
767  }
768 }
769 
770 ################################################################################################################################################################
771 
772 proc CreateProject {args} {
773  # set tcl_path [file normalize "[file dirname [info script]]"]
774  # set repo_path [file normalize $tcl_path/../..]
775 
776  if {[catch {package require cmdline} ERROR]} {
777  puts "ERROR: If you are running this script on tclsh, you can fix this by installing 'tcllib'"
778  return
779  }
780  set parameters {
781  {simlib_path.arg "" "Path of simulation libs"}
782  {verbose "If set, launch the script in verbose mode."}
783  }
784 
785  set usage "Create Vivado/ISE/Quartus/Libero/Diamond project.\nUsage: CreateProject \[OPTIONS\] <project> <repository path>\n Options:"
786 
787  if {[catch {array set options [cmdline::getoptions args $parameters $usage]}] || [llength $args] < 2 || [lindex $args 0] eq ""} {
788  Msg Info [cmdline::usage $parameters $usage]
789  return 1
790  }
791 
792  set globalSettings::DESIGN [lindex $args 0]
793  if {[file exists [lindex $args 1]]} {
794  set globalSettings::repo_path [file normalize [lindex $args 1]]
795  } else {
796  Msg Error "The second argument, [lindex $args 1], should be the repository path."
797  }
798  set globalSettings::tcl_path $globalSettings::repo_path/Hog/Tcl
799 
800 
801  if {$options(verbose) == 1} {
802  variable ::DEBUG_MODE 1
803  }
804 
805  if {[IsVivado]} {
806  if {$options(simlib_path) != ""} {
807  if {[IsRelativePath $options(simlib_path)] == 0} {
808  set globalSettings::simlib_path "$options(simlib_path)"
809  } else {
810  set globalSettings::simlib_path "$globalSettings::repo_path/$options(simlib_path)"
811  }
812  Msg Info "Simulation library path set to $options(simlib_path)"
813  } else {
814  set globalSettings::simlib_path "$globalSettings::repo_path/SimulationLib"
815  Msg Info "Simulation library path set to default $globalSettings::repo_path/SimulationLib"
816  }
817  }
818 
819 
820  set proj_dir [file normalize $globalSettings::repo_path/Top/$globalSettings::DESIGN]
821  lassign [GetConfFiles $proj_dir] conf_file sim_file pre_file post_file
822 
823  set user_repo 0
824  if {[file exists $conf_file]} {
825  Msg Info "Parsing configuration file $conf_file..."
826  SetGlobalVar PROPERTIES [ReadConf $conf_file]
827 
828  #Checking Vivado/Quartus/ISE/Libero version
829  set actual_version [GetIDEVersion]
830  lassign [GetIDEFromConf $conf_file] ide conf_version
831  if {$conf_version != "0.0.0"} {
832  set a_v [split $actual_version "."]
833  set c_v [split $conf_version "."]
834 
835  if {[llength $a_v] < 2} {
836  Msg Error "Couldn't parse IDE version: $actual_version."
837  } elseif {[llength $a_v] == 2} {
838  lappend a_v 0
839  }
840  if {[llength $c_v] < 2} {
841  Msg Error "Wrong version format in hog.conf: $conf_version."
842  } elseif {[llength $c_v] == 2} {
843  lappend c_v 0
844  }
845 
846  set comp [CompareVersions $a_v $c_v]
847  if {$comp == 0} {
848  Msg Info "Project version and $ide version match: $conf_version."
849  } elseif {$comp == 1} {
850  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\
851  If you want update this project to version $actual_version, please update the configuration file."
852  } else {
853  # tclint-disable-next-line line-length
854  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."
855  }
856  } else {
857  Msg CriticalWarning "No version found in the first line of $conf_file. \
858  It is HIGHLY recommended to replace the first line of $conf_file with: \#$ide $actual_version"
859  }
860  if {[dict exists $globalSettings::PROPERTIES main]} {
861  set main [dict get $globalSettings::PROPERTIES main]
862  dict for {p v} $main {
863  # notice the dollar in front of p: creates new variables and fill them with the value
864  Msg Info "Main property $p set to $v"
865  ##nagelfar ignore
866  set ::$p $v
867  }
868  } else {
869  Msg Error "No main section found in $conf_file, make sure it has a section called \[main\] containing the mandatory properties."
870  }
871  } else {
872  Msg Error "$conf_file was not found in your project directory, please create one."
873  }
874 
875 
876  if {[IsXilinx] || [IsQuartus]} {
877  SetGlobalVar PART
878  }
879  #Family is needed in quartus and libero only
880  if {[IsQuartus] || [IsLibero]} {
881  #Quartus only
882  SetGlobalVar FAMILY
883  if {[IsLibero]} {
884  SetGlobalVar DIE
885  SetGlobalVar PACKAGE
886  }
887  }
888 
889  if {[IsDiamond]} {
890  SetGlobalVar DEVICE
891  SetGlobalVar SYNTHESIS_TOOL "lse"
892  }
893 
894  if {[IsVivado]} {
895  SetGlobalVar TARGET_SIMULATOR "XSim"
896  }
897 
898  if {[info exists env(HOG_EXTERNAL_PATH)]} {
899  set globalSettings::HOG_EXTERNAL_PATH $env(HOG_EXTERNAL_PATH)
900  } else {
901  set globalSettings::HOG_EXTERNAL_PATH ""
902  }
903 
904  #Derived variables from now on...
905 
906  set build_dir_name "Projects"
907  set globalSettings::group_name [file dirname $globalSettings::DESIGN]
908  set globalSettings::pre_synth_file "pre-synthesis.tcl"
909  set globalSettings::post_synth_file "post-synthesis.tcl"
910  set globalSettings::pre_impl_file "pre-implementation.tcl"
911  set globalSettings::post_impl_file "post-implementation.tcl"
912  set globalSettings::pre_bit_file "pre-bitstream.tcl"
913  set globalSettings::post_bit_file "post-bitstream.tcl"
914  set globalSettings::quartus_post_module_file "quartus-post-module.tcl"
915  set globalSettings::top_path "$globalSettings::repo_path/Top/$globalSettings::DESIGN"
916  set globalSettings::list_path "$globalSettings::top_path/list"
917  set globalSettings::build_dir "$globalSettings::repo_path/$build_dir_name/$globalSettings::DESIGN"
918  set globalSettings::DESIGN [file tail $globalSettings::DESIGN]
919  set globalSettings::top_name [file tail $globalSettings::DESIGN]
920  set globalSettings::top_name [file rootname $globalSettings::top_name]
921  set globalSettings::synth_top_module "top_$globalSettings::top_name"
922  set globalSettings::user_ip_repo ""
923 
924  set globalSettings::pre_synth [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_synth_file"]
925  set globalSettings::post_synth [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_synth_file"]
926  set globalSettings::pre_impl [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_impl_file"]
927  set globalSettings::post_impl [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_impl_file"]
928  set globalSettings::pre_bit [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::pre_bit_file"]
929  set globalSettings::post_bit [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::post_bit_file"]
930  set globalSettings::quartus_post_module [file normalize "$globalSettings::tcl_path/integrated/$globalSettings::quartus_post_module_file"]
931  set globalSettings::LIBERO_MANDATORY_VARIABLES {"FAMILY" "PACKAGE" "DIE" }
932 
933  set user_hog_file "$globalSettings::repo_path/Top/hog.tcl"
934  if {[file exists $user_hog_file]} {
935  Msg Info "Sourcing user hog.tcl file..."
936  source $user_hog_file
937  }
938 
939  if {[file exists $pre_file]} {
940  Msg Info "Found pre-creation Tcl script $pre_file, executing it..."
941  source $pre_file
942  }
943 
944  if {[info exists env(HOG_IP_PATH)]} {
945  set globalSettings::HOG_IP_PATH $env(HOG_IP_PATH)
946  } else {
947  set globalSettings::HOG_IP_PATH ""
948  }
949 
955 
956  if {[IsVivado]} {
957  # Use HandleIP to pull IPs from HOG_IP_PATH if specified
958  ManageIPs
959  }
960 
961  if {[IsQuartus]} {
962  set fileName_old [file normalize "./hogTmp/.hogQsys.md5"]
963  set fileDir [file normalize "$globalSettings::build_dir/.hog/"]
964  file mkdir $fileDir
965  set fileName_new [file normalize "$fileDir/.hogQsys.md5"]
966  if {[file exists $fileName_new]} {
967  file delete $fileName_new
968  }
969  if {[file exists $fileName_old]} {
970  file rename -force $fileName_old $fileName_new
971  file delete -force -- "./hogTmp"
972  }
973  }
974 
975  if {[file exists $post_file]} {
976  Msg Info "Found post-creation Tcl script $post_file, executing it..."
977  source $post_file
978  if {[IsLibero]} {
979  # Regenerate the hierarchy in case a new file has been added
980  build_design_hierarchy
981  }
982  }
983 
984  # Check extra IPs
985  # Get project libraries and properties from list files
986  lassign [GetHogFiles \
987  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
988  -list_files ".src,.ext" \
989  "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" \
990  $globalSettings::repo_path] \
991  listLibraries listProperties listSrcSets
992  # Get project constraints and properties from list files
993  lassign [GetHogFiles \
994  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
995  -list_files ".con" \
996  "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" \
997  $globalSettings::repo_path] \
998  listConstraints listConProperties listConSets
999 
1000  lassign [GetHogFiles \
1001  -ext_path "$globalSettings::HOG_EXTERNAL_PATH" \
1002  -list_files ".sim" \
1003  "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" \
1004  $globalSettings::repo_path] \
1005  listSimLibraries listSimProperties listSimSets
1006 
1007  set old_path [pwd]
1008  cd $globalSettings::build_dir
1009  CheckExtraFiles $listLibraries $listConstraints $listSimLibraries
1010  cd $old_path
1011 
1012  if {[IsXilinx]} {
1013  set old_path [pwd]
1014  cd $globalSettings::repo_path
1015  set flavour [GetProjectFlavour $globalSettings::DESIGN]
1016  # Getting all the versions and SHAs of the repository
1017  lassign [GetRepoVersions \
1018  [file normalize $globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN] \
1019  $globalSettings::repo_path \
1020  $globalSettings::HOG_EXTERNAL_PATH \
1021  ] commit version hog_hash hog_ver top_hash top_ver libs hashes vers cons_ver cons_hash ext_names ext_hashes \
1022  xml_hash xml_ver user_ip_repos user_ip_hashes user_ip_vers
1023 
1024  set this_commit [GetSHA]
1025 
1026  if {$commit == 0} {
1027  set commit $this_commit
1028  }
1029 
1030  if {$xml_hash != ""} {
1031  set use_ipbus 1
1032  } else {
1033  set use_ipbus 0
1034  }
1035 
1036 
1037  lassign [GetDateAndTime $commit] date timee
1038  WriteGenerics "create" \
1039  $globalSettings::repo_path \
1040  $globalSettings::group_name/$globalSettings::DESIGN \
1041  $date $timee $commit $version \
1042  $top_hash $top_ver $hog_hash $hog_ver \
1043  $cons_ver $cons_hash $libs $vers $hashes \
1044  $ext_names $ext_hashes $user_ip_repos $user_ip_vers \
1045  $user_ip_hashes $flavour $xml_ver $xml_hash
1046  cd $old_path
1047  }
1048 
1049  if {[IsLibero]} {
1050  save_project
1051  }
1052 
1053  if {[IsDiamond]} {
1054  prj_project save
1055  }
1056 
1057  Msg Info "Project $globalSettings::DESIGN created successfully in [Relative $globalSettings::repo_path $globalSettings::build_dir]."
1058 }