Hog v9.9.0
launch.tcl
Go to the documentation of this file.
1 #!/usr/bin/env tclsh
2 # @file
3 # Copyright 2018-2024 The University of Birmingham
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 
18 # Launch Xilinx Vivado or ISE implementation and possibly write bitstream in text mode
19 
20 #parsing command options
21 set parameters {
22  {no_bitstream "If set, the bitstream file will not be produced."}
23  {recreate "If set, the project will be re-created if it already exists."}
24  {no_reset "If set, runs (synthesis and implementation) won't be reset before launching them."}
25  {check_syntax "If set, the HDL syntax will be checked at the beginning of the workflow."}
26  {njobs.arg 4 "Number of jobs. Default: 4"}
27  {ext_path.arg "" "Sets the absolute path for the external libraries."}
28  {lib.arg "" "Compiled simulation library path"}
29  {synth_only "If set, only the synthesis will be performed."}
30  {impl_only "If set, only the implementation will be performed. This assumes synthesis should was already done."}
31  {simset.arg "" "Simulation sets, separated by commas, to be run."}
32  {verbose "If set, launch the script in verbose mode"}
33 }
34 
35 set usage " \[OPTIONS\] <directive> <project>\n The most common <directive> values are CREATE (or C), WORKFLOW (or W), SIMULATE (or S).
36 
37 ** Directives (case insensitive):
38 - CREATE or C: Create the project, replacing it if already existing.
39 - WORKFLOW or W: Launches the complete workflow, creates the project if not existing.
40 - CREATEWORKFLOW or CW: Creates the project -even if existing- and launches the complete workflow.
41 - SIMULATE or S: Simulate the project, creating it if not existing.
42 - IMPLEMENT: Runs the implementation only, the project must already exist and be synthesised.
43 - SYNTHESIS: Runs the synthesis only, creates the project if not existing.
44 - LIST or L: Only list all the projects
45 "
46 
47 set tcl_path [file normalize "[file dirname [info script]]"]
48 source $tcl_path/hog.tcl
49 # Quartus needs extra packages and treats the argv in a different way
50 if {[IsQuartus]} {
51  load_package report
52  set argv $quartus(args)
53 }
54 
55 Msg Debug "s: $::argv0 a: $argv"
56 
57 lassign [InitLauncher $::argv0 $tcl_path $parameters $usage $argv] directive project project_name group_name repo_path old_path bin_dir top_path commands_path cmd ide
58 
59 Msg Debug "Returned by InitLauncher: $project $project_name $group_name $repo_path $old_path $bin_dir $top_path $commands_path $cmd"
60 
61 append usage [GetCustomCommands $commands_path]
62 append usage "\n** Options:"
63 
64 ######## DEFAULTS #########
65 set do_implementation 0; set do_synthesis 0; set do_bitstream 0; set do_create 0; set do_compile 0; set do_simulation 0; set recreate 0; set reset 1;
66 
67 set default_commands {
68 
69  \^C(REATE)?$ {
70  set do_create 1
71  set recreate 1
72  }
73 
74  \^I(MPL(EMENT(ATION)?)?)?$ {
75  set do_implementation 1
76  set do_bitstream 1
77  set do_compile 1
78  }
79 
80  \^SYNT(H(ESIS(E)?)?)? {
81  set do_synthesis 1
82  set do_compile 1
83  }
84 
85  \^S(IM(ULAT(ION|E)?)?)?$ {
86  set do_simulation 1
87  set do_create 1
88  }
89 
90  \^W(ORK(FLOW)?)?$ {
91  set do_implementation 1
92  set do_synthesis 1
93  set do_bitstream 1
94  set do_compile 1
95  }
96 
97  \^(CREATEWORKFLOW|CW)$ {
98  set do_implementation 1
99  set do_synthesis 1
100  set do_bitstream 1
101  set do_compile 1
102  set recreate 1
103  }
104 
105  default {
106  Msg Status "ERROR: Unknown directive $directive.\n\n[cmdline::usage $parameters $usage]"
107  exit 1
108  }
109 }
110 
111 set custom_commands [GetCustomCommands $commands_path 1]
112 
113 Msg Debug "Looking for a $directive in : $default_commands $custom_commands"
114 switch -regexp -- $directive "$default_commands $custom_commands"
115 
116 if {$cmd == -1} {
117 #This is if the project was not found
118  Msg Status "\n\nPossible projects are:"
119  ListProjects $repo_path
120  Msg Status "\n"
121  exit 1
122 } elseif {$cmd == -2} {
123  # Project not given but needed
124  Msg Status "ERROR: You must specify a project with directive $directive.\n\n[cmdline::usage $parameters $usage]"
125  Msg Status "\n Possible projects are:"
126  ListProjects $repo_path
127  Msg Status "\n"
128  exit 1
129 
130 } elseif {$cmd == 0} {
131  #This script was launched within the IDE,: Vivado, Quartus, etc
132  Msg Info "$::argv0 was launched from the IDE."
133 
134 } else {
135  # This script was launched with Tclsh, we need to check the arguments and if everything is right launche the IDE on this script and return
136  Msg Info "Launching command: $cmd..."
137 
138  # Check if the IDE is actually in the path...
139  set ret [catch {exec which $ide}]
140  if {$ret != 0} {
141  Msg Error "$ide not found in your system. Make sure to add $ide to your PATH enviromental variable."
142  exit $ret
143  }
144 
145  if {[string first libero $cmd] >= 0} {
146  # The SCRIPT_ARGS: flag of libero makes tcl crazy...
147  # Let's pipe the command into a shell script and remove it later
148  set libero_script [open "launch-libero-hog.sh" w]
149  puts $libero_script "#!/bin/sh"
150  puts $libero_script $cmd
151  close $libero_script
152  set cmd "sh launch-libero-hog.sh"
153  }
154 
155 
156 
157  set ret [catch {exec -ignorestderr {*}$cmd >@ stdout} result]
158 
159  if {$ret != 0} {
160  Msg Error "IDE returned an error state."
161  } else {
162  Msg Info "All done."
163  exit 0
164  }
165 
166  if {[string first libero $cmd] >= 0} {
167  file delete "launch-libero-hog.sh"
168  }
169 
170  exit $ret
171 }
172 
173 #After this line, we are in the IDE
174 ##################################################################################
175 
176 # We need to Import tcllib if we are using Libero
177 if {[IsLibero]} {
178  if {[info exists env(HOG_TCLLIB_PATH)]} {
179  lappend auto_path $env(HOG_TCLLIB_PATH)
180  } else {
181  puts "ERROR: To run Hog with Microsemi Libero SoC, you need to define the HOG_TCLLIB_PATH variable."
182  return
183  }
184 }
185 
186 if {[catch {package require cmdline} ERROR] || [catch {package require struct::matrix} ERROR]} {
187  puts "$ERROR\n Tcllib not found. If you are running this script on tclsh for debuggin purpose ONLY, you can fix this by installing 'tcllib'"
188  exit 1
189 }
190 
191 lassign [ GetOptions $::argv $parameters $usage] option_list arg_list
192 
193 if {[catch {array set options [cmdline::getoptions option_list $parameters $usage]}] || [llength $arg_list] != 2 } {
194  Msg Info [cmdline::usage $parameters $usage]
195  exit 1
196 } else {
197  set main_folder [file normalize "$repo_path/Projects/$project_name/$project.runs/"]
198  if {[IsLibero]} {
199  set main_folder [file normalize "$repo_path/Projects/$project_name/"]
200  }
201  set main_sim_folder [file normalize "$repo_path/Projects/$project_name/$project.sim/"]
202  set check_syntax 0
203  set ext_path ""
204  set simlib_path ""
205 
206  #Quartus only
207  set project_path [file normalize "$repo_path/Projects/$project_name/"]
208 }
209 
210 
211 if { $options(no_bitstream) == 1 } {
212  set do_bitstream 0
213  set do_compile 0
214 }
215 
216 if { $options(recreate) == 1 } {
217  set recreate 1
218 }
219 
220 if { $options(synth_only) == 1} {
221  set do_implementation 0
222  set do_synthesis 1
223  set do_bitstream 0
224  set do_create 1
225  set do_compile 1
226 }
227 
228 if { $options(impl_only) == 1} {
229  set do_implementation 0
230  set do_synthesis 0
231  set do_bitstream 0
232  set do_create 0
233  set do_compile 1
234 }
235 
236 
237 if { $options(no_reset) == 1 } {
238  set reset 0
239 }
240 
241 if { $options(check_syntax) == 1 } {
242  set check_syntax 1
243 }
244 
245 if { $do_simulation == 1 } {
246  set simsets $options(simset)
247 }
248 
249 if { $options(ext_path) != ""} {
250  set ext_path $options(ext_path)
251 }
252 
253 if {$options(lib)!= ""} {
254  set lib_path [file normalize $options(lib)]
255 } else {
256  if {[info exists env(HOG_SIMULATION_LIB_PATH)]} {
257  set lib_path $env(HOG_SIMULATION_LIB_PATH)
258  } else {
259  if {[file exists "$repo_path/SimulationLib"]} {
260  set lib_path [file normalize "$repo_path/SimulationLib"]
261  } else {
262  set lib_path ""
263  }
264  }
265 }
266 
267 
268 
269 if { $options(verbose) == 1 } {
270  variable ::DEBUG_MODE 1
271 }
272 
273 Msg Info "Number of jobs set to $options(njobs)."
274 
275 
276 if {[IsXilinx]} {
277 
278  ############# Vivado or ISE ####################
279 
280  #Go to Hog/Tcl
281  cd $tcl_path
282 
283  ############# CREATE or OPEN project ############
284  if {[IsISE]} {
285  set project_file [file normalize $repo_path/Projects/$project_name/$project.ppr]
286  } else {
287  set project_file [file normalize $repo_path/Projects/$project_name/$project.xpr]
288  }
289 
290  if {[file exists $project_file]} {
291  Msg Info "Found project file $project_file for $project_name."
292  set proj_found 1
293  } else {
294  Msg Info "Project file not found for $project_name."
295  set proj_found 0
296  }
297 
298  if {($proj_found == 0 || $recreate == 1) && ($do_synthesis == 1 || $do_create == 1)} {
299  Msg Info "Creating (possibly replacing) the project $project_name..."
300  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post
301 
302  if {[file exists $conf]} {
303  #Still not sure of the difference between project and project_name
304  CreateProject -simlib_path $lib_path $project_name $repo_path
305  } else {
306  Msg Error "Project $project_name is incomplete: no hog.conf file found, please create one..."
307  }
308  } else {
309  Msg Info "Opening existing project file $project_file..."
310  file mkdir "$repo_path/Projects/$project_name/$project.gen/sources_1"
311  open_project $project_file
312  }
313 
314  ########## CHECK SYNTAX ###########
315  if { $check_syntax == 1 } {
316  if {[IsISE]} {
317  Msg Info "Checking syntax option is not supported by Xilinx PlanAhead. Skipping.."
318  } else {
319  Msg Info "Checking syntax for project $project_name..."
320  set syntax [check_syntax -return_string]
321 
322  if {[string first "CRITICAL" $syntax ] != -1} {
323  check_syntax
324  exit 1
325  }
326  }
327  } else {
328  Msg Debug "Skipping syntax check for project $project_name"
329  }
330 
331  ############# SYNTH ###############
332  if {$reset == 1 && $do_create == 0} {
333  Msg Info "Resetting run before launching synthesis..."
334  reset_run synth_1
335 
336  }
337 
338  if {[IsISE]} {
339  source $tcl_path/../../Hog/Tcl/integrated/pre-synthesis.tcl
340  }
341 
342  if {$do_synthesis == 1} {
343  launch_runs synth_1 -jobs $options(njobs) -dir $main_folder
344  wait_on_run synth_1
345  set prog [get_property PROGRESS [get_runs synth_1]]
346  set status [get_property STATUS [get_runs synth_1]]
347  Msg Info "Run: synth_1 progress: $prog, status : $status"
348 
349  # Copy IP reports in bin/
350  set ips [get_ips *]
351 
352  #go to repository path
353  cd $tcl_path/../..
354 
355  lassign [GetRepoVersions [file normalize ./Top/$project_name] $repo_path $ext_path ] sha
356  set describe [GetHogDescribe $sha $repo_path]
357  Msg Info "Git describe set to $describe"
358 
359  foreach ip $ips {
360  set xci_file [get_property IP_FILE $ip]
361 
362  set xci_path [file dirname $xci_file]
363  set xci_ip_name [file rootname [file tail $xci_file]]
364  foreach rptfile [glob -nocomplain -directory $xci_path *.rpt] {
365  file copy $rptfile $bin_dir/$project_name-$describe/reports
366  }
367 
368  # Let's leave the following commented part
369  # We moved the Handle ip to the post-synthesis, in that case we can't use get_runs so to find out which IP was run, we loop over the directories enedind with _synth_1 in the .runs directory
370  #
371  # ######### Copy IP to IP repository
372  # if {[IsVivado]} {
373  # set gen_path [get_property IP_OUTPUT_DIR $ip]
374  # if {($ip_path != "")} {
375  # # IP is not in the gitlab repo
376  # set force 0
377  # if [info exist runs] {
378  # if {[lsearch $runs $ip\_synth_1] != -1} {
379  # Msg Info "$ip was synthesized, will force the copy to the IP repository..."
380  # set force 1
381  # }
382  # }
383  # Msg Info "Copying synthesised IP $xci_ip_name ($xci_file) to $ip_path..."
384  # HandleIP push $xci_file $ip_path $repo_path $gen_path $force
385  # }
386  # }
387 
388  }
389 
390  if {$prog ne "100%"} {
391  Msg Error "Synthesis error, status is: $status"
392  }
393  } else {
394  Msg Debug "Skipping synthesis (and IP handling)..."
395  }
396 
397  ############### IMPL ###################
398 
399  if {$do_implementation == 1 } {
400 
401  Msg Info "Starting implementation flow..."
402  if { $reset == 1 && $do_create == 0} {
403  Msg Info "Resetting run before launching implementation..."
404  reset_run impl_1
405  }
406 
407  if {[IsISE]} {source $tcl_path/../../Hog/Tcl/integrated/pre-implementation.tcl}
408  launch_runs impl_1 -jobs $options(njobs) -dir $main_folder
409  wait_on_run impl_1
410  if {[IsISE]} {source $tcl_path/../../Hog/Tcl/integrated/post-implementation.tcl}
411 
412  set prog [get_property PROGRESS [get_runs impl_1]]
413  set status [get_property STATUS [get_runs impl_1]]
414  Msg Info "Run: impl_1 progress: $prog, status : $status"
415 
416  # Check timing
417  if {[IsISE]} {
418 
419  set status_file [open "$main_folder/timing.txt" "w"]
420  puts $status_file "## $project_name Timing summary"
421 
422  set f [open [lindex [glob "$main_folder/impl_1/*.twr" 0]]]
423  set errs -1
424  while {[gets $f line] >= 0} {
425  if { [string match "Timing summary:" $line] } {
426  while {[gets $f line] >= 0} {
427  if { [string match "Timing errors:*" $line] } {
428  set errs [regexp -inline -- {[0-9]+} $line]
429  }
430  if { [string match "*Footnotes*" $line ] } {
431  break
432  }
433  puts $status_file "$line"
434  }
435  }
436  }
437 
438  close $f
439  close $status_file
440 
441  if {$errs == 0} {
442  Msg Info "Time requirements are met"
443  file rename -force "$main_folder/timing.txt" "$main_folder/timing_ok.txt"
444  set timing_ok 1
445  } else {
446  Msg CriticalWarning "Time requirements are NOT met"
447  file rename -force "$main_folder/timing.txt" "$main_folder/timing_error.txt"
448  set timing_ok 0
449  }
450  }
451 
452  if {[IsVivado]} {
453  set wns [get_property STATS.WNS [get_runs [current_run]]]
454  set tns [get_property STATS.TNS [get_runs [current_run]]]
455  set whs [get_property STATS.WHS [get_runs [current_run]]]
456  set ths [get_property STATS.THS [get_runs [current_run]]]
457 
458  if {$wns >= 0 && $whs >= 0} {
459  Msg Info "Time requirements are met"
460  set status_file [open "$main_folder/timing_ok.txt" "w"]
461  set timing_ok 1
462  } else {
463  Msg CriticalWarning "Time requirements are NOT met"
464  set status_file [open "$main_folder/timing_error.txt" "w"]
465  set timing_ok 0
466  }
467 
468  Msg Status "*** Timing summary ***"
469  Msg Status "WNS: $wns"
470  Msg Status "TNS: $tns"
471  Msg Status "WHS: $whs"
472  Msg Status "THS: $ths"
473 
474  struct::matrix m
475  m add columns 5
476  m add row
477 
478  puts $status_file "## $project_name Timing summary"
479 
480  m add row "| **Parameter** | \"**value (ns)**\" |"
481  m add row "| --- | --- |"
482  m add row "| WNS: | $wns |"
483  m add row "| TNS: | $tns |"
484  m add row "| WHS: | $whs |"
485  m add row "| THS: | $ths |"
486 
487  puts $status_file [m format 2string]
488  puts $status_file "\n"
489  if {$timing_ok == 1} {
490  puts $status_file " Time requirements are met."
491  } else {
492  puts $status_file "Time requirements are **NOT** met."
493  }
494  puts $status_file "\n\n"
495  close $status_file
496  }
497 
498  if {$prog ne "100%"} {
499  Msg Error "Implementation error"
500  }
501 
502  if {$do_bitstream == 1} {
503  Msg Info "Starting write bitstream flow..."
504  if {[IsISE]} {
505  # PlanAhead command
506  Msg Info "running pre-bitstream"
507  source $tcl_path/../../Hog/Tcl/integrated/pre-bitstream.tcl
508  launch_runs impl_1 -to_step Bitgen $options(njobs) -dir $main_folder
509  wait_on_run impl_1
510  Msg Info "running post-bitstream"
511  source $tcl_path/../../Hog/Tcl/integrated/post-bitstream.tcl
512  } elseif { [string first Vivado [version]] ==0} {
513  # Vivado command
514  launch_runs impl_1 -to_step [BinaryStepName [get_property PART [current_project]]] $options(njobs) -dir $main_folder
515  wait_on_run impl_1
516  }
517 
518  set prog [get_property PROGRESS [get_runs impl_1]]
519  set status [get_property STATUS [get_runs impl_1]]
520  Msg Info "Run: impl_1 progress: $prog, status : $status"
521 
522  if {$prog ne "100%"} {
523  Msg Error "Write bitstream error, status is: $status"
524  }
525 
526  if {[IsVivado]} {
527  Msg Status "*** Timing summary (again) ***"
528  Msg Status "WNS: $wns"
529  Msg Status "TNS: $tns"
530  Msg Status "WHS: $whs"
531  Msg Status "THS: $ths"
532  }
533  }
534 
535  #Go to repository path
536  cd $repo_path
537 
538  lassign [GetRepoVersions [file normalize ./Top/$project_name] $repo_path] sha
539  set describe [GetHogDescribe $sha $repo_path]
540  Msg Info "Git describe set to $describe"
541 
542  set dst_dir [file normalize "$bin_dir/$project_name\-$describe"]
543 
544  file mkdir $dst_dir
545 
546  #Version table
547  if {[file exists $main_folder/versions.txt]} {
548  file copy -force $main_folder/versions.txt $dst_dir
549  } else {
550  Msg Warning "No versions file found in $main_folder/versions.txt"
551  }
552  #Timing file
553  set timing_files [ glob -nocomplain "$main_folder/timing_*.txt" ]
554  set timing_file [file normalize [lindex $timing_files 0]]
555 
556  if {[file exists $timing_file]} {
557  file copy -force $timing_file $dst_dir/
558  } else {
559  Msg Warning "No timing file found, not a problem if running locally"
560  }
561 
562  }
563 
564  if {$do_simulation == 1} {
565  ##################### SIMULATION #######################
566  set simsets_todo ""
567  if {$simsets != ""} {
568  set simsets_todo [split $simsets ","]
569  Msg Info "Will run only the following simsets (if they exist): $simsets_todo"
570  }
571 
572  set failed []
573  set success []
574  set sim_dic [dict create]
575 
576  Msg Info "Retrieving list of simulation sets..."
577  foreach s [get_filesets] {
578  set type [get_property FILESET_TYPE $s]
579  if {$type eq "SimulationSrcs"} {
580  if {$simsets_todo != "" && $s ni $simsets_todo} {
581  Msg Info "Skipping $s as it was not specified with the -simset option..."
582  continue
583  }
584  if {[file exists "$repo_path/Top/$project_name/list/$s.sim"]} {
585  set fp [open "$repo_path/Top/$project_name/list/$s.sim" r]
586  set file_data [read $fp]
587  close $fp
588  set data [split $file_data "\n"]
589  set n [llength $data]
590  Msg Info "$n lines read from $s.sim"
591 
592  set firstline [lindex $data 0]
593  # Find simulator
594  if { [regexp {^ *\#Simulator} $firstline] } {
595  set simulator_prop [regexp -all -inline {\S+} $firstline]
596  set simulator [string tolower [lindex $simulator_prop 1]]
597  } else {
598  Msg Warning "Simulator not set in $s.sim. The first line of $s.sim should be #Simulator <SIMULATOR_NAME>, where <SIMULATOR_NAME> can be xsim, questa, modelsim, riviera, activehdl, ies, or vcs, e.g. #Simulator questa. Setting simulator by default as xsim."
599  set simulator "xsim"
600  }
601  if {$simulator eq "skip_simulation"} {
602  Msg Info "Skipping simulation for $s"
603  continue
604  }
605  set_property "target_simulator" $simulator [current_project]
606  Msg Info "Creating simulation scripts for $s..."
607  if { [file exists $repo_path/Top/$project_name/pre-simulation.tcl] } {
608  Msg Info "Running $repo_path/Top/$project_name/pre-simulation.tcl"
609  source $repo_path/Top/$project_name/pre-simulation.tcl
610  }
611  if { [file exists $repo_path/Top/$project_name/pre-$s-simulation.tcl] } {
612  Msg Info "Running $repo_path/Top/$project_name/pre-$s-simulation.tcl"
613  source Running $repo_path/Top/$project_name/pre-$s-simulation.tcl
614  }
615  current_fileset -simset $s
616  set sim_dir $main_sim_folder/$s/behav
617  if { ([string tolower $simulator] eq "xsim") } {
618  set sim_name "xsim:$s"
619  if { [catch { launch_simulation -simset [get_filesets $s] } log] } {
620  Msg CriticalWarning "Simulation failed for $s, error info: $::errorInfo"
621  lappend failed $sim_name
622  } else {
623  lappend success $sim_name
624  }
625  } else {
626  Msg Info "Simulation library path is set to $lib_path."
627  set simlib_ok 1
628  if {!([file exists $lib_path])} {
629  Msg Warning "Could not find simulation library path: $lib_path, $simulator simulation will not work."
630  set simlib_ok 0
631  }
632 
633  if {$simlib_ok == 1} {
634  set_property "compxlib.${simulator}_compiled_library_dir" [file normalize $lib_path] [current_project]
635  launch_simulation -scripts_only -simset [get_filesets $s]
636  set top_name [get_property TOP $s]
637  set sim_script [file normalize $sim_dir/$simulator/]
638  Msg Info "Adding simulation script location $sim_script for $s..."
639  lappend sim_scripts $sim_script
640  dict append sim_dic $sim_script $s
641  } else {
642  Msg Error "Cannot run $simulator simulations without a valid library path"
643  exit -1
644  }
645  }
646  }
647  }
648  }
649 
650  if {[info exists sim_scripts]} {
651  # Only for modelsim/questasim
652  Msg Info "Generating IP simulation targets, if any..."
653 
654  foreach ip [get_ips] {
655  generate_target simulation -quiet $ip
656  }
657 
658 
659  Msg Status "\n\n"
660  Msg Info "====== Starting simulations runs ======"
661  Msg Status "\n\n"
662 
663  foreach s $sim_scripts {
664  cd $s
665  set cmd ./compile.sh
666  Msg Info " ************* Compiling: $s ************* "
667  lassign [ExecuteRet $cmd] ret log
668  set sim_name "comp:[dict get $sim_dic $s]"
669  if {$ret != 0} {
670  Msg CriticalWarning "Compilation failed for $s, error info: $::errorInfo"
671  lappend failed $sim_name
672  } else {
673  lappend success $sim_name
674  }
675  Msg Info "###################### Compilation log starts ######################"
676  Msg Info "\n\n$log\n\n"
677  Msg Info "###################### Compilation log ends ######################"
678 
679 
680  if { [file exists "./elaborate.sh"] } {
681  set cmd ./elaborate.sh
682  Msg Info " ************* Elaborating: $s ************* "
683  lassign [ExecuteRet $cmd] ret log
684  set sim_name "elab:[dict get $sim_dic $s]"
685  if {$ret != 0} {
686  Msg CriticalWarning "Elaboration failed for $s, error info: $::errorInfo"
687  lappend failed $sim_name
688  } else {
689  lappend success $sim_name
690  }
691  Msg Info "###################### Elaboration log starts ######################"
692  Msg Info "\n\n$log\n\n"
693  Msg Info "###################### Elaboration log ends ######################"
694  }
695  set cmd ./simulate.sh
696  Msg Info " ************* Simulating: $s ************* "
697  lassign [ExecuteRet $cmd] ret log
698 
699  # If HOG_SIMPASS_STR is set, search for the string and update return code from simulation if the string is not found in simulation log
700  if {[info exists env(HOG_SIMPASS_STR)]} {
701  Msg Info "Searching for simulation pass string: '$env(HOG_SIMPASS_STR)'"
702  if {[string first $env(HOG_SIMPASS_STR) $log] == -1} {
703  set ret 1
704  }
705  }
706 
707  set sim_name "sim:[dict get $sim_dic $s]"
708  if {$ret != 0} {
709  Msg CriticalWarning "Simulation failed for $s, error info: $::errorInfo"
710  lappend failed $sim_name
711  } else {
712  lappend success $sim_name
713  }
714  Msg Info "###################### Simulation log starts ######################"
715  Msg Info "\n\n$log\n\n"
716  Msg Info "###################### Simulation log ends ######################"
717 
718  }
719  }
720 
721 
722  if {[llength $success] > 0} {
723  set successes [join $success "\n"]
724  Msg Info "The following simulation sets were successful:\n\n$successes\n\n"
725  }
726 
727  if {[llength $failed] > 0} {
728  set failures [join $failed "\n"]
729  Msg Error "The following simulation sets have failed:\n\n$failures\n\n"
730  exit -1
731  } elseif {[llength $success] > 0} {
732  Msg Info "All the [llength $success] compilations, elaborations and simulations were successful."
733  }
734 
735  Msg Info "Simulation done."
736 
737  }
738 
739 
740 
741 
742 } elseif [IsQuartus] {
743  ############## Quartus ########################
744  set argv ""
745  #############################
746  # Recreate the project file #
747  #############################
748  if { [catch {package require ::quartus::project} ERROR] } {
749  Msg Error "$ERROR\n Can not find package ::quartus::project"
750  cd $old_path
751  return 1
752  } else {
753  Msg Info "Loaded package ::quartus::project"
754  }
755 
756  if {[file exists "$project_path/$project.qpf" ]} {
757  Msg Info "Found project file $project.qpf for $project_name."
758  set proj_found 1
759  } else {
760  Msg Warning "Project file not found for $project_name."
761  set proj_found 0
762  }
763 
764  if { $proj_found == 0 || $recreate == 1 || $do_create == 1} {
765  Msg Info "Creating (possibly replacing) the project $project_name..."
766  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post tcl_file
767 
768  if {[file exists $conf]} {
769  CreateProject -simlib_path $lib_path $project_name $repo_path
770  } else {
771  Msg Error "Project $project_name is incomplete: not Tcl file or hog.conf file found."
772  }
773  }
774 
775  if {[file exists "$project_path" ]} {
776  cd $project_path
777  } else {
778  Msg Error "Project directory not found for $project_name."
779  return 1
780  }
781 
782  if { ![is_project_open ] } {
783  Msg Info "Opening existing project file $project_name..."
784  project_open $project -current_revision
785  }
786 
787  Msg Info "Number of jobs set to $options(njobs)."
788  set_global_assignment -name NUM_PARALLEL_PROCESSORS $options(njobs)
789 
790  load_package flow
791 
792  ################
793  # CHECK SYNTAX #
794  ################
795  if { $check_syntax == 1 } {
796  Msg Info "Checking syntax for project $project_name..."
797  lassign [GetHogFiles -list_files "*.src" "$repo_path/Top/$project_name/list/" $repo_path] src_files dummy
798  dict for {lib files} $src_files {
799  foreach f $files {
800  set file_extension [file extension $f]
801  if { $file_extension == ".vhd" || $file_extension == ".vhdl" || $file_extension == ".v" || $file_extension == ".sv" } {
802  if { [catch {execute_module -tool map -args "--analyze_file=$f"} result]} {
803  Msg Error "\nResult: $result\n"
804  Msg Error "Check syntax failed.\n"
805  } else {
806  if { $result == "" } {
807  Msg Info "Check syntax was successful for $f.\n"
808  } else {
809  Msg Warning "Found syntax error in file $f:\n $result\n"
810  }
811  }
812  }
813  }
814  }
815  }
816 
817  # keep track of the current revision and of the top level entity name
818  lassign [GetRepoVersions [file normalize $repo_path/Top/$project_name] $repo_path ] sha
819  set describe [GetHogDescribe $sha $repo_path]
820  #set top_level_name [ get_global_assignment -name TOP_LEVEL_ENTITY ]
821  set revision [get_current_revision]
822  if { $do_compile == 1 } {
823  if {[catch {execute_flow -compile} result]} {
824  Msg Error "Result: $result\n"
825  Msg Error "Full compile flow failed. See the report file.\n"
826  } else {
827  Msg Info "Full compile Flow was successful for revision $revision.\n"
828  }
829  if {[file exists "output_files/versions.txt" ]} {
830  set dst_dir [file normalize "$repo_path/bin/$project_name\-$describe"]
831  file mkdir $dst_dir
832  file copy -force "output_files/versions.txt" $dst_dir
833  }
834  } else {
835  #############################
836  # Analysis and Synthesis
837  #############################
838  if { $do_synthesis == 1 } {
839 
840 
841  #run PRE_FLOW_SCRIPT by hand
842  set tool_and_command [ split [get_global_assignment -name PRE_FLOW_SCRIPT_FILE] ":"]
843  set tool [lindex $tool_and_command 0]
844  set pre_flow_script [lindex $tool_and_command 1]
845  set cmd "$tool -t $pre_flow_script quartus_map $project $revision"
846  #Close project to avoid conflict with pre synthesis script
847  project_close
848 
849  lassign [ExecuteRet {*}$cmd ] ret log
850  if {$ret != 0} {
851  Msg Warning "Can not execute command $cmd"
852  Msg Warning "LOG: $log"
853  } else {
854  Msg Info "Pre flow script executed!"
855  }
856 
857  # Re-open project
858  if { ![is_project_open ] } {
859  Msg Info "Re-opening project file $project_name..."
860  project_open $project -current_revision
861  }
862 
863  # Execute synthesis
864  if {[catch {execute_module -tool map -args "--parallel"} result]} {
865  Msg Error "Result: $result\n"
866  Msg Error "Analysis & Synthesis failed. See the report file.\n"
867  } else {
868  Msg Info "Analysis & Synthesis was successful for revision $revision.\n"
869  }
870  }
871  #############################
872  # Place & Route
873  #############################
874  if { $do_implementation == 1 } {
875  if {[catch {execute_module -tool fit} result]} {
876  Msg Error "Result: $result\n"
877  Msg Error "Place & Route failed. See the report file.\n"
878  } else {
879  Msg Info "\nINFO: Place & Route was successful for revision $revision.\n"
880  }
881  #############################
882  # Generate bitstream
883  #############################
884  if { $do_bitstream == 1 } {
885  if {[catch {execute_module -tool asm} result]} {
886  Msg Error "Result: $result\n"
887  Msg Error "Generate bitstream failed. See the report file.\n"
888  } else {
889  Msg Info "Generate bitstream was successful for revision $revision.\n"
890  }
891  }
892  #############################
893  # Additional tools to be run on the project
894  #############################
895  #TODO
896  if {[catch {execute_module -tool sta -args "--do_report_timing"} result]} {
897  Msg Error "Result: $result\n"
898  Msg Error "Time Quest failed. See the report file.\n"
899  } else {
900  Msg Info "Time Quest was successfully run for revision $revision.\n"
901  load_package report
902  load_report
903  set panel "Timing Analyzer||Timing Analyzer Summary"
904  set device [ get_report_panel_data -name $panel -col 1 -row_name "Device Name" ]
905  set timing_model [ get_report_panel_data -name $panel -col 1 -row_name "Timing Models" ]
906  set delay_model [ get_report_panel_data -name $panel -col 1 -row_name "Delay Model" ]
907  #set slack [ get_timing_analysis_summary_results -slack ]
908  Msg Info "*******************************************************************"
909  Msg Info "Device: $device"
910  Msg Info "Timing Models: $timing_model"
911  Msg Info "Delay Model: $delay_model"
912  Msg Info "Slack:"
913  #Msg Info $slack
914  Msg Info "*******************************************************************"
915  }
916  }
917  }
918 
919  # close project
920  project_close
921 
922 } elseif {[IsLibero]} {
923 
924  ############# CREATE or OPEN project ############
925  set project_file [file normalize $repo_path/Projects/$project_name/$project.prjx]
926 
927  if {[file exists $project_file]} {
928  Msg Info "Found project file $project_file for $project_name."
929  set proj_found 1
930  } else {
931  Msg Info "Project file not found for $project_name."
932  set proj_found 0
933  }
934 
935  if {($proj_found == 0 || $recreate == 1) && ($do_synthesis == 1 || $do_create == 1)} {
936  Msg Info "Creating (possibly replacing) the project $project_name..."
937  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post
938 
939  if {[file exists $conf]} {
940  CreateProject -simlib_path $lib_path $project_name $repo_path
941  } else {
942  Msg Error "Project $project_name is incomplete: no hog.conf file found, please create one..."
943  }
944  } else {
945  Msg Info "Opening existing project file $project_file..."
946  open_project -file $project_file -do_backup_on_convert 1 -backup_file {./Projects/$project_file.zip}
947  }
948 
949  ########## CHECK SYNTAX ###########
950  if { $check_syntax == 1 } {
951  Msg Info "Checking syntax option is not supported for Microchip Libero Soc yet. Skipping.."
952  }
953 
954  defvar_set -name RWNETLIST_32_64_MIXED_FLOW -value 0
955 
956  ############# SYNTH ###############
957 
958  if {$do_synthesis == 1} {
959  Msg Info "Run SYNTHESIS..."
960  if {[catch {run_tool -name {SYNTHESIZE} }] } {
961  Msg Error "SYNTHESIZE FAILED!"
962  } else {
963  Msg Info "SYNTHESIZE PASSED!"
964  }
965  } else {
966  Msg Debug "Skipping synthesis (and IP handling)..."
967  }
968 
969  ############### IMPL ###################
970 
971  if {$do_implementation == 1 } {
972 
973  Msg Info "Starting implementation flow..."
974  if {[catch {run_tool -name {PLACEROUTE} }] } {
975  Msg Error "PLACEROUTE FAILED!"
976  } else {
977  Msg Info "PLACEROUTE PASSED."
978  }
979 
980  # source $tcl_path/../../Hog/Tcl/integrated/post-implementation.tcl
981 
982  # Check timing
983  Msg Info "Run VERIFYTIMING ..."
984  if {[catch {run_tool -name {VERIFYTIMING} -script {Hog/Tcl/integrated/libero_timing.tcl} }] } {
985  Msg CriticalWarning "VERIFYTIMING FAILED!"
986  } else {
987  Msg Info "VERIFYTIMING PASSED \n"
988  }
989 
990 
991  if {$do_bitstream == 1} {
992  Msg Info "Starting write bitstream flow..."
993  Msg Info "Run GENERATEPROGRAMMINGDATA ..."
994  if {[catch {run_tool -name {GENERATEPROGRAMMINGDATA} }] } {
995  Msg Error "GENERATEPROGRAMMINGDATA FAILED!"
996  } else {
997  Msg Info "GENERATEPROGRAMMINGDATA PASSED."
998  }
999  Msg Info "Sourcing Hog/Tcl/integrated/post-bitstream.tcl"
1000  source $tcl_path/../../Hog/Tcl/integrated/post-bitstream.tcl
1001  }
1002 
1003  #Go to repository path
1004  cd $repo_path
1005 
1006  lassign [GetRepoVersions [file normalize ./Top/$project_name] $repo_path] sha
1007  set describe [GetHogDescribe $sha $repo_path]
1008  Msg Info "Git describe set to $describe"
1009 
1010  set dst_dir [file normalize "$bin_dir/$project_name\-$describe"]
1011  file mkdir $dst_dir/reports
1012 
1013  #Version table
1014  if {[file exists $main_folder/versions.txt]} {
1015  file copy -force $main_folder/versions.txt $dst_dir
1016  } else {
1017  Msg Warning "No versions file found in $main_folder/versions.txt"
1018  }
1019  #Timing file
1020  set timing_file_path [file normalize "$repo_path/Projects/timing_libero.txt"]
1021  if {[file exists $timing_file_path]} {
1022  file copy -force $timing_file_path $dst_dir/reports/Timing.txt
1023  set timing_file [open $timing_file_path "r"]
1024  set status_file [open "$dst_dir/timing.txt" "w"]
1025  puts $status_file "## $project_name Timing summary\n\n"
1026  puts $status_file "| | |"
1027  puts $status_file "| --- | --- |"
1028  while {[gets $timing_file line] >= 0} {
1029  if { [string match "SUMMARY" $line] } {
1030  while {[gets $timing_file line] >= 0} {
1031  if { [string match "END SUMMARY" $line ] } {
1032  break
1033  }
1034  if {[string first ":" $line] == -1} {
1035  continue
1036  }
1037  set out_string "| [string map {: | } $line] |"
1038  puts $status_file "$out_string"
1039  }
1040  }
1041  }
1042  } else {
1043  Msg Warning "No timing file found, not a problem if running locally"
1044  }
1045 
1046  }
1047 
1048 
1049 } else {
1050  Msg Error "Impossible condition. You need to run this in an IDE."
1051  exit 1
1052 }
1053 
1054 Msg Info "All done."
1055 cd $old_path