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