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