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