Hog Hog2025.1-6
post-bitstream.tcl
Go to the documentation of this file.
1 #!/usr/bin/env tclsh
2 # Copyright 2018-2025 The University of Birmingham
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 # @file
17 # The post bitstream script copies binary files, reports and other files to the bin directory in your repository.
18 # This script is automatically integrated into the Vivado/Quartus workflow by the Create Project script.
19 
20 set old_path [pwd]
21 set tcl_path [file normalize "[file dirname [info script]]/.."]
22 source $tcl_path/hog.tcl
23 set repo_path [file normalize "$tcl_path/../../"]
24 
25 # Import tcllib
26 if {[IsLibero] || [IsDiamond]} {
27  if {[info exists env(HOG_TCLLIB_PATH)]} {
28  lappend auto_path $env(HOG_TCLLIB_PATH)
29  } else {
30  puts "ERROR: To run Hog with Microsemi Libero SoC, you need to define the HOG_TCLLIB_PATH variable."
31  return
32  }
33 }
34 
35 if {[info exists env(HOG_EXTERNAL_PATH)]} {
36  set ext_path $env(HOG_EXTERNAL_PATH)
37  Msg Info "Found environment variable HOG_EXTERNAL_PATH, setting path for external files to $ext_path..."
38 } else {
39  set ext_path ""
40 }
41 
42 set bin_dir [file normalize "$repo_path/bin"]
43 
44 if {[IsXilinx]} {
45  # Binary files are called .bit for ISE and for Vivado unless the chip is a Versal
46  set fw_file_ext "bit"
47 
48  # Vivado + PlanAhead
49  if {[IsISE]} {
50  # planAhead
51  set work_path [get_property DIRECTORY [get_runs impl_1]]
52  } else {
53  # Vivado
54  set work_path $old_path
55  if {[IsVersal [get_property PART [current_design]]]} {
56  #In Vivado if a Versal chip is used, the main binary file is called .bif
57  set fw_file_ext "bif"
58  }
59  }
60 
61  set main_file [file normalize [lindex [glob -nocomplain "$work_path/*.$fw_file_ext"] 0]]
62  set proj_name [file tail [file normalize $work_path/../../]]
63  set proj_dir [file normalize "$work_path/../.."]
64 
65  set top_name [file rootname [file tail $main_file]]
66 
67  set additional_ext "bin ltx pdi"
68 
69  set xml_dir [file normalize "$work_path/../xml"]
70  set run_dir [file normalize "$work_path/.."]
71 
72 } elseif {[IsQuartus]} {
73  # Quartus
74  ##nagelfar ignore Unknown variable
75  set proj_name [lindex $quartus(args) 1]
76  set proj_dir [pwd]
77  set xml_dir [file normalize "$repo_path/xml"]
78  set run_dir [file normalize "$proj_dir"]
79  set name [file rootname [file tail [file normalize [pwd]]]]
80  # programming object file
81  set pof_file [file normalize "$proj_dir/output_files/$proj_name.pof"]
82  # SRAM Object File
83  set sof_file [file normalize "$proj_dir/output_files/$proj_name.sof"]
84  # raw binary file
85  set rbf_file [file normalize "$proj_dir/output_files/$proj_name.rbf"]
86  #raw programming file
87  set rpd_file [file normalize "$proj_dir/output_files/$proj_name.rpd"]
88  # signal tap file
89  set stp_file [file normalize "$proj_dir/output_files/$proj_name.stp"]
90  #source and probes file
91  set spf_file [file normalize "$proj_dir/output_files/$proj_name.spf"]
92 
93 } elseif {[IsLibero]} {
94  # Libero
95  ##nagelfar ignore Unknown variable
96  set proj_name $project
97  ##nagelfar ignore Unknown variable
98  set proj_dir $main_folder
99  set map_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.map"] 0]]
100  set sap_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.sap"] 0]]
101  set srd_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.srd"] 0]]
102  set srm_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.srm"] 0]]
103  set srs_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.srs"] 0]]
104  set srr_file [file normalize [lindex [glob -nocomplain "$proj_dir/synthesis/*.srr"] 0]]
105  set top_name [file rootname [file tail $srr_file]]
106  set stxt_files [glob -nocomplain "$proj_dir/synthesis/*.txt"]
107  set scsv_files [glob -nocomplain "$proj_dir/synthesis/*.csv"]
108  set slog_files [glob -nocomplain "$proj_dir/synthesis/*.log"]
109  set srpt_files [glob -nocomplain "$proj_dir/synthesis/*.rpt"]
110  set dtxt_files [glob -nocomplain "$proj_dir/designer/$top_name/*.txt"]
111  set dcsv_files [glob -nocomplain "$proj_dir/designer/$top_name/*.csv"]
112  set dlog_files [glob -nocomplain "$proj_dir/designer/$top_name/*.log"]
113  set drpt_files [glob -nocomplain "$proj_dir/designer/$top_name/*.rpt"]
114  set xml_dir [file normalize "$repo_path/xml"]
115 
116 } elseif {[IsDiamond]} {
117  set proj_dir [file normalize "[pwd]/.."]
118  set proj_name [file tail $proj_dir]
119  set project $proj_name
120  set xml_dir [file normalize "$repo_path/xml"]
121  set main_file [file normalize "$proj_dir/Implementation0/${proj_name}_Implementation0" ]
122 } else {
123  #tcl shell
124  set work_path $old_path
125  set fw_file [file normalize [lindex [glob -nocomplain "$work_path/*.bit"] 0]]
126  set proj_name [file tail [file normalize $work_path/../../]]
127  set proj_dir [file normalize "$work_path/../.."]
128 
129  set top_name [file rootname [file tail $fw_file]]
130 
131  set main_file [file normalize "$work_path/$top_name.bit"]
132  set bin_file [file normalize "$work_path/$top_name.bin"]
133  set ltx_file [file normalize "$work_path/$top_name.ltx"]
134 
135  set xml_dir [file normalize "$work_path/../xml"]
136  set run_dir [file normalize "$work_path/.."]
137 }
138 
139 set group_name [GetGroupName $proj_dir "$tcl_path/../.."]
140 # Go to repository path
141 cd $repo_path
142 
143 Msg Info "Evaluating Git sha for $proj_name..."
144 lassign [GetRepoVersions [file normalize ./Top/$group_name/$proj_name] $repo_path] sha
145 
146 set describe [GetHogDescribe $sha $repo_path]
147 Msg Info "Hog describe set to: $describe"
148 
149 set dst_dir [file normalize "$bin_dir/$group_name/$proj_name\-$describe"]
150 set dst_xml [file normalize "$dst_dir/xml"]
151 
152 Msg Info "Creating $dst_dir..."
153 file mkdir $dst_dir
154 
155 set ts [clock format [clock seconds] -format {%Y-%m-%d-%H-%M}]
156 
157 
158 # Vivado
159 if {[IsXilinx] && [file exists $main_file]} {
160  set dst_main [file normalize "$dst_dir/$proj_name\-$describe.$fw_file_ext"]
161  Msg Info "Copying main binary file $main_file into $dst_main..."
162  file copy -force $main_file $dst_main
163 
164  # LTX file for ILA, needs a special treatment...
165  set ltx_file "$work_path/$top_name.ltx"
166  write_debug_probes -quiet $ltx_file
167 
168  # Additional files
169  foreach e $additional_ext {
170  set orig [file normalize "$work_path/$top_name.$e"]
171  set dst [file normalize "$dst_dir/$proj_name\-$describe.$e"]
172  if {[file exists $orig]} {
173  Msg Info "Copying $orig file into $dst..."
174  file copy -force $orig $dst
175  } else {
176  Msg Debug "File: $orig not found."
177  }
178 
179  }
180 
181 
182 
183 } elseif {[IsQuartus]} {
184 
185  set dst_pof [file normalize "$dst_dir/$name\-$describe.pof"]
186  set dst_sof [file normalize "$dst_dir/$name\-$describe.sof"]
187  set dst_rbf [file normalize "$dst_dir/$name\-$describe.rbf"]
188  set dst_rpd [file normalize "$dst_dir/$name\-$describe.rpd"]
189  set dst_stp [file normalize "$dst_dir/$name\-$describe.stp"]
190  set dst_spf [file normalize "$dst_dir/$name\-$describe.spf"]
191  set dst_xml [file normalize "$dst_dir/xml"]
192 
193  Msg Info "Evaluating differences with last commit..."
194  set found_uncommitted 0
195  set diff [Git diff]
196  if {$diff != ""} {
197  set found_uncommitted 1
198  Msg Warning "Found non committed changes:"
199  Msg Status "$diff"
200  set fp [open "$dst_dir/diff_postbistream.txt" w+]
201  puts $fp "$diff"
202  close $fp
203  }
204 
205  if {$found_uncommitted == 0} {
206  Msg Info "No uncommitted changes found."
207  }
208 
209  #pof file
210  if {[file exists $pof_file]} {
211  Msg Info "Copying pof file $pof_file into $dst_pof..."
212  file copy -force $pof_file $dst_pof
213  } else {
214  Msg Info "No pof file found: $pof_file, that is not a problem"
215  }
216 
217  #Reports
218  file mkdir $dst_dir/reports
219  set reps [glob -nocomplain "$proj_dir/output_files/*.rpt"]
220 
221  if {[file exists [lindex $reps 0]]} {
222  file copy -force {*}$reps $dst_dir/reports
223  } else {
224  Msg Warning "No reports found in $proj_dir/output_files subfolders"
225  }
226 
227  # sof File
228  if {[file exists $sof_file]} {
229  Msg Info "Copying sof file $sof_file into $dst_sof..."
230  file copy -force $sof_file $dst_sof
231  } else {
232  Msg Info "No sof file found: $sof_file, that is not a problem"
233  }
234 
235 
236  #rbf rpd
237  if { [file exists $rbf_file] || [file exists $rpd_file] } {
238  if {[file exists $rbf_file]} {
239  file copy -force $rbf_file $dst_rbf
240  }
241  if {[file exists $rpd_file]} {
242  file copy -force $rpd_file $dst_rpd
243  }
244  } else {
245  Msg Info "No rbf or rpd file found: this is not a problem"
246  }
247 
248  # stp and spf File
249  if {[file exists $stp_file] || [file exists $spf_file]} {
250  if {[file exists $stp_file]} {
251  file copy -force $stp_file $dst_stp
252  }
253  if {[file exists $spf_file]} {
254  file copy -force $spf_file $dst_spf
255  }
256  } else {
257  Msg Info "No stp or spf file found: that is not a problem"
258  }
259 
260 } elseif {[IsLibero] } {
261 
262  set dst_map [file normalize "$dst_dir/$project\-$describe.map"]
263  set dst_sap [file normalize "$dst_dir/$project\-$describe.sap"]
264  set dst_srd [file normalize "$dst_dir/$project\-$describe.srd"]
265  set dst_srm [file normalize "$dst_dir/$project\-$describe.srm"]
266  set dst_srs [file normalize "$dst_dir/$project\-$describe.srs"]
267  set dst_srr [file normalize "$dst_dir/$project\-$describe.srr"]
268  set dst_rpt [file normalize "$dst_dir/reports"]
269  set dst_xml [file normalize "$dst_dir/xml"]
270 
271  file mkdir $dst_dir/reports
272 
273  if {[file exists $map_file]} {
274  Msg Info "Copying map file $map_file into $dst_map..."
275  file copy -force $map_file $dst_map
276  }
277 
278  if {[file exists $sap_file]} {
279  Msg Info "Copying sap file $sap_file into $dst_sap..."
280  file copy -force $sap_file $dst_sap
281  }
282 
283  if {[file exists $srd_file]} {
284  Msg Info "Copying srd file $srd_file into $dst_srd..."
285  file copy -force $srd_file $dst_srd
286  }
287 
288  if {[file exists $srm_file]} {
289  Msg Info "Copying srm file $srm_file into $dst_srm..."
290  file copy -force $srm_file $dst_map
291  }
292 
293  if {[file exists $srs_file]} {
294  Msg Info "Copying srs file $srs_file into $dst_srs..."
295  file copy -force $srs_file $dst_srs
296  }
297 
298  if {[file exists $srr_file]} {
299  Msg Info "Copying srr file $srr_file into $dst_srr..."
300  file copy -force $srr_file $dst_srr
301  }
302 
303 
304  Msg Info "Copying synth txt files $stxt_files into $dst_rpt..."
305  file copy -force {*}$stxt_files $dst_rpt
306  Msg Info "Copying synth csv files $scsv_files into $dst_rpt..."
307  file copy -force {*}$scsv_files $dst_rpt
308  Msg Info "Copying synth log files $slog_files into $dst_rpt..."
309  file copy -force {*}$slog_files $dst_rpt
310  Msg Info "Copying synth rpt files $srpt_files into $dst_rpt..."
311  file copy -force {*}$srpt_files $dst_rpt
312 
313  Msg Info "Copying impl txt files $dtxt_files into $dst_rpt..."
314  file copy -force {*}$dtxt_files $dst_rpt
315  Msg Info "Copying impl csv files $dcsv_files into $dst_rpt..."
316  file copy -force {*}$dcsv_files $dst_rpt
317  Msg Info "Copying impl log files $dlog_files into $dst_rpt..."
318  file copy -force {*}$dlog_files $dst_rpt
319  Msg Info "Copying impl rpt files $drpt_files into $dst_rpt..."
320  file copy -force {*}$drpt_files $dst_rpt
321 
322 } elseif {[IsDiamond] } {
323  set dst_main [file normalize "$dst_dir/$proj_name\-$describe.bit"]
324  Msg Info "Copying main binary file $main_file.bit into $dst_main..."
325  file copy -force $main_file.bit $dst_main
326  Msg Info "Copying binary generation log $main_file.bgn into $dst_dir/reports..."
327  file copy -force $main_file.bgn $dst_dir/reports
328 
329 
330 } else {
331  Msg CriticalWarning "Firmware binary file not found."
332 }
333 
334 
335 # IPbus XML
336 if {[file exists $xml_dir]} {
337  Msg Info "XML directory found, copying xml files from $xml_dir to $dst_xml..."
338  if {[file exists $dst_xml]} {
339  Msg Info "Directory $dst_xml exists, deleting it..."
340  file delete -force $dst_xml
341  }
342  file copy -force $xml_dir $dst_xml
343 }
344 
345 # Zynq XSA Export
346 if {[IsXilinx]} {
347  # Vivado
348  # automatically export for zynqs (checking via regex)
349  set export_xsa false
350  set part [get_property part [current_project]]
351 
352  if { [IsZynq $part] || [IsVersal $part]} {
353  Msg Info "SoC FPGA detected (Zynq or Versal), automatically enabling XSA file creation. To disable it, add 'EXPORT_XSA = false' in the \[hog\] section of hog.conf."
354  set export_xsa true
355  }
356 
357  # check for explicit EXPORT_XSA flag in hog.conf
358  set properties [ReadConf [lindex [GetConfFiles $repo_path/Top/$group_name/$proj_name] 0]]
359  if {[dict exists $properties "hog"]} {
360  set propDict [dict get $properties "hog"]
361  if {[dict exists $propDict "EXPORT_XSA"]} {
362  set export_xsa [dict get $propDict "EXPORT_XSA"]
363  }
364  }
365 
366  if {[string compare [string tolower $export_xsa] "true"]==0} {
367  # there is a bug in Vivado 2020.1, check for that version and warn
368  # that we can't export XSAs
369  regexp -- {Vivado v([0-9]{4}\.[0-9,A-z,_,\.]*) } [version] -> VIVADO_VERSION
370  if {[string compare "2020.1" $VIVADO_VERSION]==0} {
371  Msg Warning "Vivado 2020.1, a patch must be applied to Vivado to export XSA Files, c.f. https://www.xilinx.com/support/answers/75210.html"
372  } else {
373 
374  set dst_xsa [file normalize "$dst_dir/${proj_name}\-$describe.xsa"]
375  Msg Info "Generating XSA File at $dst_xsa"
376  if { [IsVersal $part] } {
377  # Run user pre-platform file
378  set user_pre_platform_file "./Top/$group_name/$proj_name/pre-platform.tcl"
379  if {[file exists $user_pre_platform_file]} {
380  Msg Info "Sourcing user pre-platform file $user_pre_platform_file"
381  source $user_pre_platform_file
382  }
383  set pdi_post_imp [file normalize "$work_path/$top_name.pdi"]
384  set_property platform.full_pdi_file $pdi_post_imp [current_project]
385  Msg Info "XSA file will be generated for Versal with this PDI: $pdi_post_imp"
386  write_hw_platform -fixed -force -file "$dst_xsa"
387  } else {
388  write_hw_platform -include_bit -fixed -force -file "$dst_xsa"
389  }
390  }
391  }
392 }
393 
394 
395 # Run user post-bitstream file
396 set user_post_bitstream_file "./Top/$group_name/$proj_name/post-bitstream.tcl"
397 if {[file exists $user_post_bitstream_file]} {
398  Msg Info "Sourcing user post-bitstream file $user_post_bitstream_file"
399  source $user_post_bitstream_file
400 }
401 
402 cd $old_path
403 Msg Info "All done."