Hog v9.50.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  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..*"}
83  set_msg_config -suppress -regexp -string {".*File '.*.xci' referenced by design '.*' could not be found..*"}
84 
85  # File inside .bd
86  set_msg_config -suppress -id {IP_Flow 19-3664}
87  # This is due to simulations in project with NoC
88  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} }
89  }
90  # Create project
91  create_project -force [file tail $globalSettings::DESIGN] $globalSettings::build_dir -part $globalSettings::PART
92  file mkdir "$globalSettings::build_dir/[file tail $globalSettings::DESIGN].gen/sources_1"
93  if { [IsVersal $globalSettings::PART] } {
94  Msg Info "This project uses a Versal device."
95  }
96 
97  ## Set project properties
98  set obj [get_projects [file tail $globalSettings::DESIGN] ]
99  set_property "target_language" "VHDL" $obj
100 
101  if {[IsVivado]} {
102  set_property "simulator_language" "Mixed" $obj
103  foreach simulator [GetSimulators] {
104  set_property "compxlib.${simulator}_compiled_library_dir" $globalSettings::simlib_path $obj
105  }
106  set_property "default_lib" "xil_defaultlib" $obj
107  ## Enable VHDL 2008
108  set_param project.enableVHDL2008 1
109  set_property "enable_vhdl_2008" 1 $obj
110  ## Enable Automatic compile order mode, otherwise we cannot find the right top module...
111  set_property source_mgmt_mode All [current_project]
112  # Set PART Immediately
113  Msg Debug "Setting PART = $globalSettings::PART"
114  set_property PART $globalSettings::PART [current_project]
115  }
116 
118 
119  } elseif {[IsQuartus]} {
120  package require ::quartus::project
121  #QUARTUS_ONLY
122  if {[string equal $globalSettings::FAMILY "quartus_only"]} {
123  Msg Error "You must specify a device Family for Quartus"
124  } else {
125  file mkdir $globalSettings::build_dir
126  cd $globalSettings::build_dir
127  if {[is_project_open]} {
128  project_close
129  }
130 
131  file delete {*}[glob -nocomplain $globalSettings::DESIGN.q*]
132 
133  project_new -family $globalSettings::FAMILY -overwrite -part $globalSettings::PART $globalSettings::DESIGN
134  set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
135 
137  }
138  } elseif {[IsLibero]} {
139  if {[file exists $globalSettings::build_dir]} {
140  file delete -force $globalSettings::build_dir
141  }
142  new_project -location $globalSettings::build_dir -name [file tail $globalSettings::DESIGN] -die $globalSettings::DIE -package $globalSettings::PACKAGE -family $globalSettings::FAMILY -hdl VHDL
143  } elseif {[IsDiamond]} {
144  if {[file exists $globalSettings::build_dir]} {
145  file delete -force $globalSettings::build_dir
146  }
147  set old_dir [pwd]
148  file mkdir $globalSettings::build_dir
149  cd $globalSettings::build_dir
150  prj_project new -name [file tail $globalSettings::DESIGN] -dev $globalSettings::DEVICE -synthesis $globalSettings::SYNTHESIS_TOOL
151  cd $old_dir
153  } else {
154  puts "Creating project for $globalSettings::DESIGN part $globalSettings::PART"
155  puts "Configuring project settings:"
156  puts " - simulator_language: Mixed"
157  puts " - target_language: VHDL"
158  puts " - simulator: QuestaSim"
159  puts "Adding IP directory \"$globalSettings::user_ip_repo\" to the project "
160  }
161 
162 }
163 
164 proc AddProjectFiles {} {
165 
166  if {[IsXilinx]} {
167  #VIVADO_ONLY
168  ## Create fileset src
169  if {[string equal [get_filesets -quiet sources_1] ""]} {
170  create_fileset -srcset sources_1
171  }
172  set sources "sources_1"
173  } else {
174  set sources 0
175  }
176 
177 
178  ###############
179  # CONSTRAINTS #
180  ###############
181  if {[IsXilinx]} {
182  #VIVADO_ONLY
183  # Create 'constrs_1' fileset (if not found)
184  if {[string equal [get_filesets -quiet constrs_1] ""]} {
185  create_fileset -constrset constrs_1
186  }
187 
188  # Set 'constrs_1' fileset object
189  set constraints [get_filesets constrs_1]
190  }
191 
192  ##############
193  # READ FILES #
194  ##############
195 
196  if {[file isdirectory $globalSettings::list_path]} {
197  set list_files [glob -directory $globalSettings::list_path "*"]
198  } else {
199  Msg Error "No list directory found at $globalSettings::list_path"
200  }
201 
202  if {[IsISE]} {
203  source $globalSettings::tcl_path/utils/cmdline.tcl
204  }
205 
206  # Add first .src, .sim, and .ext list files
207  AddHogFiles {*}[GetHogFiles -list_files {.src,.sim,.ext} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path ]
208 
209  ## Set synthesis TOP
210  SetTopProperty $globalSettings::synth_top_module $sources
211 
212  # Libero needs the top files to be set before adding the constraints
213  AddHogFiles {*}[GetHogFiles -list_files {.con} -ext_path $globalSettings::HOG_EXTERNAL_PATH $globalSettings::list_path $globalSettings::repo_path ]
214  ## Set simulation Properties
215 
216  ## Libero Properties must be set after that root has been defined
217  if {[IsLibero]} {
219  }
220 }
221 
222 
223 ## @brief Set Vivado Report strategy for implementation
224 #
225 # @param[in] obj the project object
226 #
227 proc CreateReportStrategy {obj} {
228  #TODO: Add ReportStrategy for Quartus/Libero and Diamond
229 
230  if {[IsVivado]} {
231  ## Vivado Report Strategy
232  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
233  # No report strategy needed
234  Msg Info "No report strategy needed for implementation"
235  } else {
236  # Report strategy needed since version 2017.3
237  set_property set_report_strategy_name 1 $obj
238  set_property report_strategy {Vivado Implementation Default Reports} $obj
239  set_property set_report_strategy_name 0 $obj
240 
241  set reports [get_report_configs -of_objects $obj]
242  # Create 'impl_1_place_report_utilization_0' report (if not found)
243  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } {
244  create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1
245  }
246  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0]
247  if { $obj != "" } {
248 
249  }
250 
251  # Create 'impl_1_route_report_drc_0' report (if not found)
252  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } {
253  create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1
254  }
255  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0]
256  if { $obj != "" } {
257 
258  }
259 
260  # Create 'impl_1_route_report_power_0' report (if not found)
261  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } {
262  create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1
263  }
264  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0]
265  if { $obj != "" } {
266 
267  }
268 
269  # Create 'impl_1_route_report_timing_summary' report (if not found)
270  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary] "" ] } {
271  create_report_config -report_name impl_1_route_report_timing_summary -report_type report_timing_summary:1.0 -steps route_design -runs impl_1
272  }
273  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary]
274  if { $obj != "" } {
275  Msg Info "Report timing created successfully"
276  }
277 
278  # Create 'impl_1_route_report_utilization' report (if not found)
279  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization] "" ] } {
280  create_report_config -report_name impl_1_route_report_utilization -report_type report_utilization:1.0 -steps route_design -runs impl_1
281  }
282  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_utilization]
283  if { $obj != "" } {
284  Msg Info "Report utilization created successfully"
285  }
286 
287 
288  # Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found)
289  if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } {
290  create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1
291  }
292  set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0]
293  if { $obj != "" } {
294  set_property -name "options.max_paths" -value "10" -objects $obj
295  set_property -name "options.warn_on_violation" -value "1" -objects $obj
296  }
297 
298  }
299  } else {
300  Msg Info "Won't create any report strategy, not in Vivado"
301  }
302 }
303 
304 
305 ## @brief configure synthesis.
306 #
307 # The method uses the content of globalSettings::SYNTH_FLOW and globalSettings::SYNTH_STRATEGY to set the implementation strategy and flow.
308 # The function also sets Hog specific pre and post synthesis scripts
309 #
310 proc ConfigureSynthesis {} {
311  if {[IsXilinx]} {
312  #VIVADO ONLY
313  ## Create 'synthesis ' run (if not found)
314  if {[string equal [get_runs -quiet synth_1] ""]} {
315  create_run -name synth_1 -part $globalSettings::PART -constrset constrs_1
316  } else {
317 
318  }
319 
320  set obj [get_runs synth_1]
321  set_property "part" $globalSettings::PART $obj
322  }
323 
324  ## set pre synthesis script
325  if {$globalSettings::pre_synth_file ne ""} {
326  if {[IsXilinx]} {
327  #Vivado Only
328  if {[IsVivado]} {
329  if {[get_filesets -quiet utils_1] != ""} {
330  AddFile $globalSettings::pre_synth [get_filesets -quiet utils_1]
331  }
332  set_property STEPS.SYNTH_DESIGN.TCL.PRE $globalSettings::pre_synth $obj
333  }
334  } elseif {[IsQuartus]} {
335  #QUARTUS only
336  set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:$globalSettings::pre_synth
337 
338  } elseif {[IsLibero]} {
339  configure_tool -name {SYNTHESIZE} -params SYNPLIFY_TCL_FILE:$globalSettings::pre_synth
340  } elseif {[IsDiamond]} {
341  prj_impl pre_script "syn" $globalSettings::pre_synth
342  }
343 
344  Msg Debug "Setting $globalSettings::pre_synth to be run before synthesis"
345  }
346 
347  ## set post synthesis script
348  if {$globalSettings::post_synth_file ne ""} {
349  if {[IsXilinx]} {
350  #Vivado Only
351  if {[IsVivado]} {
352  if {[get_filesets -quiet utils_1] != ""} {
353  AddFile $globalSettings::post_synth [get_filesets -quiet utils_1]
354  }
355  set_property STEPS.SYNTH_DESIGN.TCL.POST $globalSettings::post_synth $obj
356  }
357  } elseif {[IsQuartus]} {
358  #QUARTUS only
359  set_global_assignment -name POST_MODULE_SCRIPT_FILE quartus_sh:$globalSettings::quartus_post_module
360 
361  } elseif {[IsDiamond]} {
362  prj_impl post_script "syn" $globalSettings::post_synth
363  }
364  Msg Debug "Setting $globalSettings::post_synth to be run after synthesis"
365  }
366 
367 
368  if {[IsXilinx]} {
369  #VIVADO ONLY
370  ## set the current synth run
371  current_run -synthesis $obj
372 
373  ## Report Strategy
374  if {[string equal [get_property -quiet report_strategy $obj] ""]} {
375  # No report strategy needed
376  Msg Debug "No report strategy needed for synthesis"
377 
378  } else {
379  # Report strategy needed since version 2017.3
380  set_property set_report_strategy_name 1 $obj
381  set_property report_strategy {Vivado Synthesis Default Reports} $obj
382  set_property set_report_strategy_name 0 $obj
383  # Create 'synth_1_synth_report_utilization_0' report (if not found)
384  if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } {
385  create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1
386  }
387  set reports [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]
388  }
389  } elseif {[IsQuartus]} {
390  #QUARTUS only
391  #TO BE DONE
392 
393  } elseif {[IsLibero]} {
394  #TODO: LIBERO
395  } elseif {[IsDiamond]} {
396  #TODO: Diamond
397  } else {
398  Msg info "Reporting strategy for synthesis"
399  }
400 }
401 
402 ## @brief configure implementation.
403 #
404 # The configuration is based on the content of globalSettings::IMPL_FLOW and globalSettings::IMPL_STRATEGY
405 # The function also sets Hog specific pre- and- post implementation and, pre- and post- implementation scripts
406 #
407 proc ConfigureImplementation {} {
408  set obj ""
409  if {[IsXilinx]} {
410  # Create 'impl_1' run (if not found)
411  if {[string equal [get_runs -quiet impl_1] ""]} {
412  create_run -name impl_1 -part $globalSettings::PART -constrset constrs_1 -parent_run synth_1
413  }
414 
415  set obj [get_runs impl_1]
416  set_property "part" $globalSettings::PART $obj
417 
418  set_property "steps.[BinaryStepName $globalSettings::PART].args.readback_file" "0" $obj
419  set_property "steps.[BinaryStepName $globalSettings::PART].args.verbose" "0" $obj
420 
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 
569  if { [ string tolower $prop_name ] != "ip_repo_paths" } {
570  if {[ string tolower $prop_name] != "part"} {
571  # Part is already set
572  Msg Debug "Setting $prop_name = $prop_val"
573  set_property $prop_name $prop_val [current_project]
574  }
575  } else {
576  set ip_repo_list [regsub -all {\s+} $prop_val " $globalSettings::repo_path/"]
577  set ip_repo_list $globalSettings::repo_path/$ip_repo_list
578  set user_repo "1"
579  Msg Info "Setting $ip_repo_list as user IP repository..."
580  if {[IsISE]} {
581  set_property ip_repo_paths "$ip_repo_list" [current_fileset]
582  } else {
583  set_property ip_repo_paths "$ip_repo_list" [current_project]
584  }
585  update_ip_catalog
586  }
587  }
588  }
589  # Setting Run Properties
590  foreach run [get_runs -quiet] {
591  if {[dict exists $globalSettings::PROPERTIES $run]} {
592  Msg Info "Setting properties for run: $run..."
593  set run_props [dict get $globalSettings::PROPERTIES $run]
594  #set_property -dict $run_props $run
595  set stragety_str "STRATEGY strategy Strategy"
596  Msg Debug "Setting Strategy and Flow for run $run (if specified in hog.conf)"
597  foreach s $stragety_str {
598  if {[dict exists $run_props $s]} {
599  set prop [dict get $run_props $s]
600  set_property $s $prop $run
601  set run_props [dict remove $run_props $s]
602  Msg Warning "A strategy for run $run has been defined inside hog.conf. This prevents Hog to compare the project properties. 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 but is not added to the project in any list file. Hog cannot track it."
625  } else {
626  #Add file tu utils_1 to avoid warning
627  AddFile $globalSettings::repo_path/$prop_val [get_filesets -quiet utils_1]
628  }
629  set_property $prop_name $utility_file $run
630  } else {
631  Msg Warning "Impossible to set property $prop_name to $prop_val. File is missing"
632  }
633  } else {
634  set_property $prop_name $prop_val $run
635  }
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 
774 # set tcl_path [file normalize "[file dirname [info script]]"]
775 # set repo_path [file normalize $tcl_path/../..]
776 
777  if {[catch {package require cmdline} ERROR]} {
778  puts "ERROR: If you are running this script on tclsh, you can fix this by installing 'tcllib'"
779  return
780  }
781  set parameters {
782  {simlib_path.arg "" "Path of simulation libs"}
783  {verbose "If set, launch the script in verbose mode."}
784  }
785 
786  set usage "Create Vivado/ISE/Quartus/Libero/Diamond project.\nUsage: CreateProject \[OPTIONS\] <project> <repository path>\n Options:"
787 
788  if {[catch {array set options [cmdline::getoptions args $parameters $usage]}] || [llength $args] < 2 ||[lindex $args 0] eq""} {
789  Msg Info [cmdline::usage $parameters $usage]
790  return 1
791  }
792 
793  set globalSettings::DESIGN [lindex $args 0]
794  if {[file exists [lindex $args 1]]} {
795  set globalSettings::repo_path [file normalize [lindex $args 1]]
796  } else {
797  Msg Error "The second argument, [lindex $args 1], should be the repository path."
798  }
799  set globalSettings::tcl_path $globalSettings::repo_path/Hog/Tcl
800 
801 
802  if { $options(verbose) == 1 } {
803  variable ::DEBUG_MODE 1
804  }
805 
806  if {[IsVivado]} {
807  if {$options(simlib_path)!= ""} {
808  if {[IsRelativePath $options(simlib_path)] == 0} {
809  set globalSettings::simlib_path "$options(simlib_path)"
810  } else {
811  set globalSettings::simlib_path "$globalSettings::repo_path/$options(simlib_path)"
812  }
813  Msg Info "Simulation library path set to $options(simlib_path)"
814  } else {
815  set globalSettings::simlib_path "$globalSettings::repo_path/SimulationLib"
816  Msg Info "Simulation library path set to default $globalSettings::repo_path/SimulationLib"
817  }
818  }
819 
820 
821  set proj_dir [file normalize $globalSettings::repo_path/Top/$globalSettings::DESIGN]
822  lassign [GetConfFiles $proj_dir] conf_file sim_file pre_file post_file
823 
824  set user_repo 0
825  if {[file exists $conf_file]} {
826  Msg Info "Parsing configuration file $conf_file..."
827  SetGlobalVar PROPERTIES [ReadConf $conf_file]
828 
829  #Checking Vivado/Quartus/ISE/Libero version
830  set actual_version [GetIDEVersion]
831  lassign [GetIDEFromConf $conf_file] ide conf_version
832  if {$conf_version != "0.0.0"} {
833 
834 
835  set a_v [split $actual_version "."]
836  set c_v [split $conf_version "."]
837 
838  if { [llength $a_v] < 2} {
839  Msg Error "Couldn't parse IDE version: $actual_version."
840  } elseif {[llength $a_v] == 2} {
841  lappend a_v 0
842  }
843  if { [llength $c_v] < 2} {
844  Msg Error "Wrong version format in hog.conf: $conf_version."
845  } elseif {[llength $c_v] == 2} {
846  lappend c_v 0
847  }
848 
849  set comp [CompareVersions $a_v $c_v]
850  if {$comp == 0} {
851  Msg Info "Project version and $ide version match: $conf_version."
852  } elseif {$comp == 1} {
853  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, if you want update this project to version $actual_version, please update the configuration file."
854  } else {
855  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."
856  }
857  } else {
858  Msg CriticalWarning "No version found in the first line of $conf_file. 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 -ext_path "$globalSettings::HOG_EXTERNAL_PATH" -list_files ".src,.ext" "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" $globalSettings::repo_path] listLibraries listProperties listSrcSets
987  # Get project constraints and properties from list files
988  lassign [GetHogFiles -ext_path "$globalSettings::HOG_EXTERNAL_PATH" -list_files ".con" "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" $globalSettings::repo_path] listConstraints listConProperties listConSets
989 
990  lassign [GetHogFiles -ext_path "$globalSettings::HOG_EXTERNAL_PATH" -list_files ".sim" "$globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN/list/" $globalSettings::repo_path] listSimLibraries listSimProperties listSimSets
991 
992  set old_path [pwd]
993  cd $globalSettings::build_dir
994  CheckExtraFiles $listLibraries $listConstraints $listSimLibraries
995  cd $old_path
996 
997  if {[IsXilinx]} {
998  set old_path [pwd]
999  cd $globalSettings::repo_path
1000  set flavour [GetProjectFlavour $globalSettings::DESIGN]
1001  # Getting all the versions and SHAs of the repository
1002  lassign [GetRepoVersions [file normalize $globalSettings::repo_path/Top/$globalSettings::group_name/$globalSettings::DESIGN] $globalSettings::repo_path $globalSettings::HOG_EXTERNAL_PATH] commit version hog_hash hog_ver top_hash top_ver libs hashes vers cons_ver cons_hash ext_names ext_hashes xml_hash xml_ver user_ip_repos user_ip_hashes user_ip_vers
1003 
1004  set this_commit [GetSHA]
1005 
1006  if {$commit == 0 } {
1007  set commit $this_commit
1008  }
1009 
1010  if {$xml_hash != ""} {
1011  set use_ipbus 1
1012  } else {
1013  set use_ipbus 0
1014  }
1015 
1016 
1017  lassign [GetDateAndTime $commit] date timee
1018  WriteGenerics "create" $globalSettings::repo_path $globalSettings::group_name/$globalSettings::DESIGN $date $timee $commit $version $top_hash $top_ver $hog_hash $hog_ver $cons_ver $cons_hash $libs $vers $hashes $ext_names $ext_hashes $user_ip_repos $user_ip_vers $user_ip_hashes $flavour $xml_ver $xml_hash
1019  cd $old_path
1020  }
1021 
1022  if {[IsLibero]} {
1023  save_project
1024  }
1025 
1026  if {[IsDiamond]} {
1027  prj_project save
1028  }
1029 
1030  Msg Info "Project $globalSettings::DESIGN created successfully in [Relative $globalSettings::repo_path $globalSettings::build_dir]."
1031 }