/
convert_ngc.tcl
457 lines (366 loc) · 16.2 KB
/
convert_ngc.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
####################################################################################
#
# convert_ngc.tcl (write a Vivado project tcl script for re-creating project)
#
# Script created on 09/01/2014 by Nik Cimino Xilinx, Inc.)
#
# 2014.3 - v1.0 (rev 1)
# * initial version
#
####################################################################################
package require Vivado 1.2014.1
namespace eval ::tclapp::xilinx::projutils {
namespace export convert_ngc
}
namespace eval ::tclapp::xilinx::projutils {
proc convert_ngc args {
send_msg_id Vivado-projutils-325 "INFO" "
###################################### IMPORTANT ######################################
# Important: NGC format files are not supported in the Vivado Design Suite for #
# UltraScale devices. It is recommended that you regenerate the IP using the Vivado #
# Design Suite IP customization tools with native output products. Alternatively, you #
# can use the NGC2EDIF command to migrate the NGC file to EDIF format for importing. #
# However, Xilinx recommends using native Vivado IP rather than XST-generated #
# XST-generated NGC format files going forward. #
#######################################################################################
"
# Summary:
# Convert all provided NGC files to a supported format
# Argument Usage:
# [-output_dir <arg> = Script output directory path]: Directory to place all output, else the output is placed at location of NGC file
# [-format <arg> = EDIF]: Accepts 'Verilog' or 'EDIF' (Default: EDIF), specifies the desired output format
# [-add_to_project]: Adds the output files to the current project, if no project is open, then this option does nothing
# [-force]: Force overwriting of files that already exist on disk, replaces files in project if add_to_project switch was specified
# files: A list of NGC files to convert
# Return Value:
# None
# Categories: xilinxtclstore, projutils
# member variables
variable m_ngc_options
init_ngc_vars_
# process options
for { set index 0 } { $index < [ llength $args ] } { incr index } {
set option [ string trim [ lindex $args $index ] ]
switch -regexp -- $option {
"-output_dir" { incr index; set m_ngc_options(sOutputDir) [ lindex $args $index ] }
"-format" { incr index; set m_ngc_options(sFormat) [ lindex $args $index ] }
"-add_to_project" { set m_ngc_options(bAddToProject) 1 }
"-force" { set m_ngc_options(bForce) 1 }
"-verbose" { set m_ngc_options(bVerbose) 1 }
default {
# is incorrect switch specified?
if { [regexp {^-} $option] } {
send_msg_id Vivado-projutils-301 ERROR "Unknown option '$option', please type 'convert_ngc -help' for usage info.\n"
return 1
}
# positional
foreach file $option {
lappend m_ngc_options(files) $file
}
}
}
}
# all files must exist
if { [ llength $m_ngc_options(files) ] == 0 } {
send_msg_id Vivado-projutils-302 ERROR "Missing value for option 'files', please type 'convert_ngc -help' for usage info.\n"
return 1
}
set bFilesAreMissing 0
foreach file $m_ngc_options(files) {
if { ! [ file exists $file ] } {
send_msg_id Vivado-projutils-303 {CRITICAL WARNING} "Specified file does not exist: '${file}'\n"
set bFilesAreMissing 1
}
}
if { $bFilesAreMissing } {
send_msg_id Vivado-projutils-304 ERROR "Some files could not be found, see previous messages for more details\n"
}
# verify that the output dir can be created, exists after creating, is a dir, and is writable
if { [ string length $m_ngc_options(sOutputDir) ] != 0 } {
if { ! [ file exists $m_ngc_options(sOutputDir) ] } {
file mkdir $m_ngc_options(sOutputDir)
if { ! [ file exists $m_ngc_options(sOutputDir) ] } {
send_msg_id Vivado-projutils-305 ERROR "Unable to create directory: '$m_ngc_options(sOutputDir)'"
}
}
if { ! [ file isdirectory $m_ngc_options(sOutputDir) ] } {
send_msg_id Vivado-projutils-306 ERROR "The '-output_dir' must point to a directory, this is not a directory: '$m_ngc_options(sOutputDir)'"
}
if { ! [ file writable $m_ngc_options(sOutputDir) ] } {
send_msg_id Vivado-projutils-307 ERROR "The '-output_dir' specified is not writable: '$m_ngc_options(sOutputDir)'"
}
}
send_msg_id Vivado-projutils-322 INFO "The convert_ngc command does not support encrypted NGC files. If an encrypted NGC is converted, then the output netlist will have all LUTs set to zero."
# end of business logic
# perform conversion
if { [ string match -nocase "$m_ngc_options(sFormat)" "verilog" ] } {
send_msg_id Vivado-projutils-320 INFO "Converting NGC files to Verilog..."
convert_ngcs_to_verilog_ $m_ngc_options(files) $m_ngc_options(sOutputDir) $m_ngc_options(bAddToProject) $m_ngc_options(bForce) $m_ngc_options(bVerbose)
} elseif { [ string match -nocase "$m_ngc_options(sFormat)" "edif" ] } {
send_msg_id Vivado-projutils-319 INFO "Converting NGC files to EDIF..."
convert_ngcs_to_edif_ $m_ngc_options(files) $m_ngc_options(sOutputDir) $m_ngc_options(bAddToProject) $m_ngc_options(bForce) $m_ngc_options(bVerbose)
} else {
send_msg_id Vivado-projutils-318 ERROR "Unknown value '$m_ngc_options(sFormat)' provided for switch -format, expected 'EDIF' or 'Verilog'"
}
}
##########
# Common #
##########
proc init_ngc_vars_ {} {
# Summary:
# Initialize all member variables
# Argument Usage:
# None
# Return Value:
# None
# member variables
variable m_ngc_options
variable m_sEdifExt
variable m_sVerilogExt
variable m_sLogExt
variable m_bDebugLogs
array unset m_ngc_options
set m_ngc_options(sOutputDir) ""
set m_ngc_options(sFormat) "EDIF"
set m_ngc_options(bAddToProject) 0
set m_ngc_options(bForce) 0
set m_ngc_options(bVerbose) 0
set m_ngc_options(files) [list]
# static
set m_sVerilogExt ".v"
set m_sEdifExt ".edn"
set m_sLogExt ".log"
set m_bDebugLogs 0
}
proc calculate_output_file_ { _sNgcFile _sOutputDir _sExtension } {
# Summary:
# Determines the output file. If a directory is provided, then the output file points to that
# directory, else the output file points to the same directory location as the source.
# Argument Usage:
# _sNgcFile: A NGC file to calculate the output file name for
# _sOutputDir: Directory to place output, else the output is placed at location of NGC file
# _sExtension: The output file extension
# Return Value:
# The calculated output file path
set sRootName [ file rootname $_sNgcFile ]
if { [ string length $_sOutputDir ] != 0 } {
set sFileName [ file tail $sRootName ]
set sRootName [ file join ${_sOutputDir} ${sFileName} ]
}
set sOutputFile "${sRootName}${_sExtension}"
return $sOutputFile
}
proc add_ngc_conversions_to_project_ { _ngcFilesToAdd _sOutputDir _sExtension _bForce } {
# Summary:
# Adds the listed files to the project
# Argument Usage:
# _filesToAdd: List of files to add to the project
# _bForce: Removes the old files from the project before adding, ensuring new files are added
# Return Value:
# None
set filesToAdd {}
foreach ngcFile $_ngcFilesToAdd {
lappend filesToAdd [ calculate_output_file_ $ngcFile $_sOutputDir $_sExtension ]
}
if { [ catch { current_project } _error ] } {
send_msg_id Vivado-projutils-316 {CRITICAL WARNING} "Could not add converted files to project because a project is not open.\n"
} else {
if { $_bForce } {
catch { remove_files -quiet $filesToAdd } _removeError
}
if { [ catch { add_files $filesToAdd } _addError ] } {
send_msg_id Vivado-projutils-314 {CRITICAL WARNING} "Failed to add converted files to project:\n[ string trim ${_addError} ]\n"
} else {
send_msg_id Vivado-projutils-317 INFO "Added all successfully converted files to project."
}
}
}
proc report_results_ { _ngcsSucceeded _ngcsFailed _bVerbose } {
# Summary:
# Reports the conversion results (which files succeeded and which failed conversion)
# Argument Usage:
# _ngcsSucceeded: List of successfully converted NGCs
# _ngcsFailed: List of NGCs that failed conversion
# _bVerbose: Prints verbose messaging
# Return Value:
# None (messages printed)
if { $_bVerbose && ( [ llength $_ngcsSucceeded ] > 0 ) } {
send_msg_id Vivado-projutils-309 INFO "Successfully converted NGC files:\n [ join $_ngcsSucceeded \n\ \ ]"
}
if { [ llength $_ngcsFailed ] > 0 } {
send_msg_id Vivado-projutils-310 INFO "Failed to convert [ llength $_ngcsFailed ] NGC file(s):\n [ join $_ngcsFailed \n\ \ ]"
}
if { [ llength $_ngcsSucceeded ] > 0 } {
send_msg_id Vivado-projutils-311 INFO "Successfully converted [ llength $_ngcsSucceeded ] NGC file(s)."
}
#if { [ llength $_ngcsFailed ] > 0 } {
# send_msg_id Vivado-projutils-312 INFO "Failed to convert [ llength $_ngcsFailed ] NGC file(s)."
#}
if { [ llength $_ngcsFailed ] > 0 } {
send_msg_id Vivado-projutils-313 ERROR "Failed to convert one or more NGC files, see previous messages for details"
}
}
###########
# Verilog #
###########
proc convert_ngcs_to_verilog_ { _ngcFiles _sOutputDir _bAddToProject _bForce _bVerbose } {
# Summary:
# Convert all provided NGC files to Verilog format
# Argument Usage:
# _ngcFiles: A list of NGC files to convert
# _sOutputDir: Directory to place all output, else the output is placed at location of NGC file
# _bAddToProject: Adds the output files to the current project, if no project is open, then this option does nothing
# _bForce: Force overwriting of files that already exist on disk, replaces files in project if add_to_project switch was specified
# _bVerbose: Print verbose messages
# Return Value:
# None
variable m_sVerilogExt
# track success and failures, but continue on failures
set ngcsFailed {}
set ngcsSucceeded {}
foreach sNgcFile $_ngcFiles {
set sCanonicalNgcFile [ file normalize $sNgcFile ]
if { [ catch { convert_ngc_to_verilog_ $sCanonicalNgcFile $_sOutputDir $_bForce } _error ] } {
# Lower level commands always end with cause by general Tcl Interp
# ERROR: [Common 17-39] 'send_msg_id' failed due to earlier errors.
#send_msg_id Vivado-projutils-308 {CRITICAL WARNING} "Failed to convert NGC file '${sCanonicalNgcFile}' error message was:\n[ string trim ${_error} ]\n"
send_msg_id Vivado-projutils-321 {CRITICAL WARNING} "Failed to convert NGC file '${sCanonicalNgcFile}', continuing with other NGC coversions...\n"
lappend ngcsFailed $sCanonicalNgcFile
} else {
lappend ngcsSucceeded $sCanonicalNgcFile
}
}
if { $_bAddToProject } {
add_ngc_conversions_to_project_ $ngcsSucceeded $_sOutputDir $m_sVerilogExt $_bForce
}
report_results_ $ngcsSucceeded $ngcsFailed $_bVerbose
}
proc convert_ngc_to_verilog_ { _sNgcFile _sOutputDir _bForce } {
# Summary:
# Convert a provided NGC file to Verilog format
# Argument Usage:
# _ngcFile: A NGC file to convert
# _sOutputDir: Directory to place all output, else the output is placed at location of NGC file
# _bForce: Force overwriting of files that already exist on disk, replaces files in project if add_to_project switch was specified
# Return Value:
# None
variable m_sVerilogExt
variable m_sLogExt
variable m_bDebugLogs
# calculate output file name
set sOutputFile [ calculate_output_file_ $_sNgcFile $_sOutputDir $m_sVerilogExt ]
set sOutputLog [ calculate_output_file_ $_sNgcFile $_sOutputDir $m_sLogExt ]
# cleanup existing files if -force specified else error
set sForceCmd ""
if { [ file exists $sOutputFile ] } {
if { ! $_bForce } {
send_msg_id Vivado-projutils-314 ERROR "Output file exists, to overwrite specify -force: '${sOutputFile}'\n"
}
}
if { $_bForce } {
set sForceCmd " -force"
}
set sLogCmd " -quiet"
if { $m_bDebugLogs } {
file delete -force $sOutputLog ; # comment for append
set sLogCmd " >> $sOutputLog"
}
# store currently open project if there is one
set currentProject [ current_project -quiet ]
# convert
set sConversionProject "Ngc2VerilogConversionProject"
# if there was already a Ngc2VerilogConversionProject opened, then Ngc2VerilogConversionProject(2)
# is created, and this is what will be stored in sCreatedProject
set sCreatedProject [ create_project -in_memory $sConversionProject $_sOutputDir ]
current_project $sCreatedProject
set_property design_mode GateLvl [ current_fileset -srcset ]
read_edif $_sNgcFile
eval "link_design${sLogCmd}"
eval "write_verilog -mode design ${sOutputFile}${sForceCmd}${sLogCmd}"
close_project
# restore previous project as current, if it was set
if { [ llength $currentProject ] == 1 } {
current_project $currentProject
}
}
########
# EDIF #
########
proc convert_ngcs_to_edif_ { _ngcFiles _sOutputDir _bAddToProject _bForce _bVerbose } {
# Summary:
# Convert all provided NGC files to EDIF format
# Argument Usage:
# _ngcFiles: A list of NGC files to convert
# _sOutputDir: Directory to place all output, else the output is placed at location of NGC file
# _bAddToProject: Adds the output files to the current project, if no project is open, then this option does nothing
# _bForce: Force overwriting of files that already exist on disk, replaces files in project if add_to_project switch was specified
# _bVerbose: Print verbose messages
# Return Value:
# None
variable m_sEdifExt
# track success and failures, but continue on failures
set ngcsFailed {}
set ngcsSucceeded {}
foreach sNgcFile $_ngcFiles {
set sCanonicalNgcFile [ file normalize $sNgcFile ]
if { [ catch { convert_ngc_to_edif_ $sCanonicalNgcFile $_sOutputDir $_bForce } _error ] } {
# Lower level commands always end with cause by general Tcl Interp
# ERROR: [Common 17-39] 'send_msg_id' failed due to earlier errors.
#send_msg_id Vivado-projutils-308 {CRITICAL WARNING} "Failed to convert NGC file '${sCanonicalNgcFile}' error message was:\n[ string trim ${_error} ]\n"
send_msg_id Vivado-projutils-321 {CRITICAL WARNING} "Failed to convert NGC file '${sCanonicalNgcFile}', continuing with other NGC coversions...\n"
lappend ngcsFailed $sCanonicalNgcFile
} else {
lappend ngcsSucceeded $sCanonicalNgcFile
}
}
if { $_bAddToProject } {
add_ngc_conversions_to_project_ $ngcsSucceeded $_sOutputDir $m_sEdifExt $_bForce
}
report_results_ $ngcsSucceeded $ngcsFailed $_bVerbose
}
proc convert_ngc_to_edif_ { _sNgcFile _sOutputDir _bForce } {
# Summary:
# Convert a provided NGC file to EDIF format
# Argument Usage:
# _ngcFile: A NGC file to convert
# _sOutputDir: Directory to place all output, else the output is placed at location of NGC file
# _bForce: Force overwriting of files that already exist on disk, replaces files in project if add_to_project switch was specified
# Return Value:
# None
variable m_sEdifExt
variable m_sLogExt
variable m_bDebugLogs
# calculate output file name
set sOutputFile [ calculate_output_file_ $_sNgcFile $_sOutputDir $m_sEdifExt ]
set sOutputLog [ calculate_output_file_ $_sNgcFile $_sOutputDir $m_sLogExt ]
# cleanup existing files if -force specified else error
if { [ file exists $sOutputFile ] } {
if { ! $_bForce } {
send_msg_id Vivado-projutils-314 ERROR "Output file exists, to overwrite specify -force: '${sOutputFile}'\n"
}
# Not needed because -w is specified on ngc2edif
# file delete -force $sOutputFile
}
# build command
set command "_ngc2edif"
set commandPath [ auto_execok $command ]
if { [ string length $commandPath ] == 0 } {
set command "ngc2edif"
set commandPath [ auto_execok $command ]
if { [ string length $commandPath ] == 0 } {
send_msg_id Vivado-projutils-315 ERROR "Failed to find the ngc2edif executable. Check to see if ngc2edif works from the Vivado shell.\n"
}
}
if { $_bForce } {
lappend command "-w"
}
if { $m_bDebugLogs } {
lappend command "-log"
lappend command $sOutputLog
}
lappend command $_sNgcFile
lappend command $sOutputFile
# throws are caught by caller
eval "exec ${command}"
}
}; # end namespace ::tclapp::xilinx::projutils