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