Hog Hog2025.1-6
launch.tcl
Go to the documentation of this file.
1 #!/usr/bin/env tclsh
2 # @file
3 # Copyright 2018-2025 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  {all "List all projects, including test projects. Test projects have #test on the second line of hog.conf."}
33  {generate "For IPbus XMLs, it willk re create the VHDL address decode files."}
34  {xml_dir.arg "" "For IPbus XMLs, set the destination folder (default is ../<project_name>_xml)."}
35  {verbose "If set, launch the script in verbose mode"}
36 }
37 
38 set usage " \[OPTIONS\] <directive> <project>\n The most common <directive> values are CREATE (or C), WORKFLOW (or W), SIMULATE (or S).
39 
40 ** Directives (case insensitive):
41 - CREATE or C: Create the project, replacing it if already existing.
42 - WORKFLOW or W: Launches the complete workflow, creates the project if not existing.
43 - CREATEWORKFLOW or CW: Creates the project -even if existing- and launches the complete workflow.
44 - SIMULATE or S: Simulate the project, creating it if not existing.
45 - IMPLEMENT: Runs the implementation only, the project must already exist and be synthesised.
46 - SYNTHESIS: Runs the synthesis only, creates the project if not existing.
47 - LIST or L: Only list all the projects
48 - XML or X: Copy, check or create IPbus XMLs
49 "
50 
51 set tcl_path [file normalize "[file dirname [info script]]"]
52 source $tcl_path/hog.tcl
53 source $tcl_path/create_project.tcl
54 # Quartus needs extra packages and treats the argv in a different way
55 if {[IsQuartus]} {
56  load_package report
57  set argv $quartus(args)
58 }
59 
60 Msg Debug "s: $::argv0 a: $argv"
61 
62 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 list_of_options
63 array set options $list_of_options
64 
65 Msg Debug "Returned by InitLauncher: $project $project_name $group_name $repo_path $old_path $bin_dir $top_path $commands_path $cmd"
66 
67 append usage [GetCustomCommands $commands_path]
68 append usage "\n** Options:"
69 
70 ######## DEFAULTS #########
71 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; set do_ipbus_xml 0; set list_all 2;
72 
73 set default_commands {
74 
75  \^C(REATE)?$ {
76  set do_create 1
77  set recreate 1
78  }
79 
80  \^I(MPL(EMENT(ATION)?)?)?$ {
81  set do_implementation 1
82  set do_bitstream 1
83  set do_compile 1
84  }
85 
86  \^SYNT(H(ESIS(E)?)?)? {
87  set do_synthesis 1
88  set do_compile 1
89  }
90 
91  \^S(IM(ULAT(ION|E)?)?)?$ {
92  set do_simulation 1
93  set do_create 1
94  }
95 
96  \^W(ORK(FLOW)?)?$ {
97  set do_implementation 1
98  set do_synthesis 1
99  set do_bitstream 1
100  set do_compile 1
101  }
102 
103  \^(CREATEWORKFLOW|CW)$ {
104  set do_implementation 1
105  set do_synthesis 1
106  set do_bitstream 1
107  set do_compile 1
108  set recreate 1
109  }
110 
111  \^X(ML)?$ {
112  set do_ipbus_xml 1
113  }
114 
115 
116  default {
117  Msg Status "ERROR: Unknown directive $directive.\n\n[cmdline::usage $parameters $usage]"
118  exit 1
119  }
120 }
121 
122 set custom_commands [GetCustomCommands $commands_path 1]
123 
124 Msg Debug "Looking for a $directive in : $default_commands $custom_commands"
125 switch -regexp -- $directive "$default_commands $custom_commands"
126 
127 if { $options(all) == 1 } {
128  set list_all 1
129 } else {
130  set list_all 2
131 }
132 
133 if {$cmd == -1} {
134 #This is if the project was not found
135  Msg Status "\n\nPossible projects are:"
136  ListProjects $repo_path $list_all
137  Msg Status "\n"
138  exit 1
139 } elseif {$cmd == -2} {
140  # Project not given but needed
141  Msg Status "ERROR: You must specify a project with directive $directive.\n\n[cmdline::usage $parameters $usage]"
142  Msg Status "\n Possible projects are:"
143  ListProjects $repo_path $list_all
144  Msg Status "\n"
145  exit 1
146 
147 } elseif {$cmd == 0} {
148  #This script was launched within the IDE,: Vivado, Quartus, etc
149  Msg Info "$::argv0 was launched from the IDE."
150 
151 } else {
152  # This script was launched with Tclsh, we need to check the arguments and if everything is right launch the IDE on this script and return
153 
154  #### Commands to be handled in tclsh should be here ###
155  if {$do_ipbus_xml == 1} {
156  Msg Info "Handling IPbus XMLs for $project_name..."
157  #Msg Info "Returned by InitLauncher: $project $project_name $group_name $repo_path $old_path $bin_dir $top_path $commands_path $cmd"
158 
159  set proj_dir $repo_path/Top/$project_name
160 
161  if { $options(generate) == 1 } {
162  set xml_gen 1
163  } else {
164  set xml_gen 0
165  }
166 
167  if { $options(xml_dir) != "" } {
168  set xml_dst $options(xml_dir)
169  } else {
170  set xml_dst "../$project\_xml"
171  Msg Info "Using default destination $xml_dst..."
172  }
173 
174  if {[llength [glob -nocomplain $proj_dir/list/*.ipb]] > 0 } {
175  if {![file exists $xml_dst]} {
176  Msg Info "$xml_dst directory not found, creating it..."
177  file mkdir $xml_dst
178  }
179  } else {
180  Msg Error "No .ipb files found in $proj_dir/list/"
181  exit
182  }
183 
184  set ret [GetRepoVersions $proj_dir $repo_path ""]
185  set sha [lindex $ret 13]
186  set hex_ver [lindex $ret 14]
187 
188  set ver [HexVersionToString $hex_ver]
189  CopyIPbusXMLs $proj_dir $repo_path $xml_dst $ver $sha 1 $xml_gen
190 
191  exit 0
192  }
193 
194 
195 
196 
197  #### END of tclsh commands ####
198  Msg Info "Launching command: $cmd..."
199 
200  # Check if the IDE is actually in the path...
201  set ret [catch {exec which $ide}]
202  if {$ret != 0} {
203  Msg Error "$ide not found in your system. Make sure to add $ide to your PATH enviromental variable."
204  exit $ret
205  }
206 
207  if {[string first libero $cmd] >= 0} {
208  # The SCRIPT_ARGS: flag of libero makes tcl crazy...
209  # Let's pipe the command into a shell script and remove it later
210  set libero_script [open "launch-libero-hog.sh" w]
211  puts $libero_script "#!/bin/sh"
212  puts $libero_script $cmd
213  close $libero_script
214  set cmd "sh launch-libero-hog.sh"
215  }
216 
217 
218 
219  set ret [catch {exec -ignorestderr {*}$cmd >@ stdout} result]
220 
221  if {$ret != 0} {
222  Msg Error "IDE returned an error state."
223  } else {
224  Msg Info "All done."
225  exit 0
226  }
227 
228  if {[string first libero $cmd] >= 0} {
229  file delete "launch-libero-hog.sh"
230  }
231 
232  exit $ret
233 }
234 
235 #After this line, we are in the IDE
236 ##################################################################################
237 
238 # We need to Import tcllib if we are using Libero
239 if {[IsLibero] || [IsDiamond]} {
240  if {[info exists env(HOG_TCLLIB_PATH)]} {
241  lappend auto_path $env(HOG_TCLLIB_PATH)
242  } else {
243  puts "ERROR: To run Hog with Microsemi Libero SoC or Lattice Diamond, you need to define the HOG_TCLLIB_PATH variable."
244  return
245  }
246 }
247 
248 if {[catch {package require cmdline} ERROR] || [catch {package require struct::matrix} ERROR]} {
249  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'"
250  exit 1
251 }
252 
253 set run_folder [file normalize "$repo_path/Projects/$project_name/$project.runs/"]
254 if {[IsLibero]} {
255  set run_folder [file normalize "$repo_path/Projects/$project_name/"]
256 }
257 
258 set check_syntax 0
259 set ext_path ""
260 set simlib_path ""
261 
262 #Only for quartus, not used otherwise
263 set project_path [file normalize "$repo_path/Projects/$project_name/"]
264 
265 
266 if { $options(no_bitstream) == 1 } {
267  set do_bitstream 0
268  set do_compile 0
269 }
270 
271 if { $options(recreate) == 1 } {
272  set recreate 1
273 }
274 
275 if { $options(synth_only) == 1} {
276  set do_implementation 0
277  set do_synthesis 1
278  set do_bitstream 0
279  set do_create 1
280  set do_compile 1
281 }
282 
283 if { $options(impl_only) == 1} {
284  set do_implementation 1
285  set do_synthesis 0
286  set do_bitstream 0
287  set do_create 0
288  set do_compile 1
289 }
290 
291 
292 if { $options(no_reset) == 1 } {
293  set reset 0
294 }
295 
296 if { $options(check_syntax) == 1 } {
297  set check_syntax 1
298 }
299 
300 if { $do_simulation == 1 } {
301  set simsets $options(simset)
302 }
303 
304 if { $options(ext_path) != ""} {
305  set ext_path $options(ext_path)
306 }
307 
308 if {$options(lib)!= ""} {
309  set lib_path [file normalize $options(lib)]
310 } else {
311  if {[info exists env(HOG_SIMULATION_LIB_PATH)]} {
312  set lib_path $env(HOG_SIMULATION_LIB_PATH)
313  } else {
314  if {[file exists "$repo_path/SimulationLib"]} {
315  set lib_path [file normalize "$repo_path/SimulationLib"]
316  } else {
317  set lib_path ""
318  }
319  }
320 }
321 
322 
323 
324 if { $options(verbose) == 1 } {
325  variable ::DEBUG_MODE 1
326 }
327 
328 # Msg Info "Number of jobs set to $options(njobs)."
329 
330 ############## Quartus ########################
331 set argv ""
332 
333 ############# CREATE or OPEN project ############
334 if {[IsISE]} {
335  cd $tcl_path
336  set project_file [file normalize $repo_path/Projects/$project_name/$project.ppr]
337 } elseif {[IsVivado]} {
338  cd $tcl_path
339  set project_file [file normalize $repo_path/Projects/$project_name/$project.xpr]
340 } elseif {[IsQuartus]} {
341  if { [catch {package require ::quartus::project} ERROR] } {
342  Msg Error "$ERROR\n Can not find package ::quartus::project"
343  cd $old_path
344  return 1
345  } else {
346  Msg Info "Loaded package ::quartus::project"
347  load_package flow
348  }
349  set project_file "$project_path/$project.qpf"
350 } elseif {[IsLibero]} {
351  set project_file [file normalize $repo_path/Projects/$project_name/$project.prjx]
352 } elseif {[IsDiamond]} {
353  sys_install version
354  set project_file [file normalize $repo_path/Projects/$project_name/$project.ldf]
355 }
356 
357 if {[file exists $project_file]} {
358  Msg Info "Found project file $project_file for $project_name."
359  set proj_found 1
360 } else {
361  Msg Info "Project file not found for $project_name."
362  set proj_found 0
363 }
364 
365 if {($proj_found == 0 || $recreate == 1) && ($do_synthesis == 1 || $do_create == 1)} {
366  Msg Info "Creating (possibly replacing) the project $project_name..."
367  lassign [GetConfFiles $repo_path/Top/$project_name] conf sim pre post
368 
369  if {[file exists $conf]} {
370  #Still not sure of the difference between project and project_name
371  CreateProject -simlib_path $lib_path $project_name $repo_path
372  } else {
373  Msg Error "Project $project_name is incomplete: no hog.conf file found, please create one..."
374  }
375 } else {
376  Msg Info "Opening existing project file $project_file..."
377  if {[IsXilinx]} {
378  file mkdir "$repo_path/Projects/$project_name/$project.gen/sources_1"
379  }
380  OpenProject $project_file $repo_path
381 }
382 
383 
384 ########## CHECK SYNTAX ###########
385 if { $check_syntax == 1 } {
386  Msg Info "Checking syntax for project $project_name..."
387  CheckSyntax $project_name $repo_path $project_file
388 }
389 
390 ######### LaunchSynthesis ########
391 if {$do_synthesis == 1} {
392  LaunchSynthesis $reset $do_create $run_folder $project_name $repo_path $ext_path $options(njobs)
393 }
394 
395 if {$do_implementation == 1 } {
396  LaunchImplementation $reset $do_create $run_folder $project_name $repo_path $options(njobs) $do_bitstream
397 }
398 
399 
400 if {$do_bitstream == 1 && ![IsXilinx] } {
401  GenerateBitstream $run_folder $repo_path $options(njobs)
402 }
403 
404 if {$do_simulation == 1} {
405  LaunchSimulation $project_name $lib_path $simsets $repo_path
406 }
407 
408 ## CLOSE Projects
410 
411 Msg Info "All done."
412 cd $old_path