############################################################################# ## ____ ____ ## / /\/ / ## /___/ \ / ## \ \ \/ Core: sem ## \ \ Module: makedata ## / / Filename: makedata.tcl ## /___/ /\ Purpose: Format write_bistream output into VMF, ## \ \ / \ MCS, and BIN formats ## \___\/\___\ ## ############################################################################# ## ## (c) Copyright 2014-2015 Xilinx, Inc. All rights reserved. ## ## This file contains confidential and proprietary information ## of Xilinx, Inc. and is protected under U.S. and ## international copyright and other intellectual property ## laws. ## ## DISCLAIMER ## This disclaimer is not a license and does not grant any ## rights to the materials distributed herewith. Except as ## otherwise provided in a valid license issued to you by ## Xilinx, and to the maximum extent permitted by applicable ## law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND ## WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES ## AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING ## BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- ## INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and ## (2) Xilinx shall not be liable (whether in contract or tort, ## including negligence, or under any other theory of ## liability) for any loss or damage of any kind or nature ## related to, arising under or in connection with these ## materials, including for any direct, or any indirect, ## special, incidental, or consequential loss or damage ## (including loss of data, profits, goodwill, or any type of ## loss or damage suffered as a result of any action brought ## by a third party) even if such damage or loss was ## reasonably foreseeable or Xilinx had been advised of the ## possibility of the same. ## ## CRITICAL APPLICATIONS ## Xilinx products are not designed or intended to be fail- ## safe, or for use in any application requiring fail-safe ## performance, such as life-support or safety devices or ## systems, Class III medical devices, nuclear facilities, ## applications related to the deployment of airbags, or any ## other applications that could lead to death, personal ## injury, or severe property or environmental damage ## (individually and collectively, "Critical ## Applications"). Customer assumes the sole risk and ## liability of any use of Xilinx products in Critical ## Applications, subject only to applicable laws and ## regulations governing limitations on product liability. ## ## THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS ## PART OF THIS FILE AT ALL TIMES. ## ############################################################################# ## ## Script Description: ## ## The write_bitstream command generates essential bits files in a "binary ## ascii" format that must be formatted as VMF for simulation purposes and ## as MCS or BIN for device programming purposes. ## ############################################################################# proc trim_and_convert_file {srcfile dstfile headerlen} { set inputfile [open $srcfile r] for {set i 0} {$i < $headerlen} {incr i 1} { if {[gets $inputfile line] < 0} { puts "File $srcfile has fewer than $headerlen lines." return } } set datalen 0 set outputfile [open $dstfile w] while {[gets $inputfile line] >= 0} { set num 0 set power 1 for {set i [string length $line]} {$i > 0} {incr i -1} { if {[string index $line [expr {$i - 1}]] eq "1"} { incr num $power } set power [expr $power * 2] } set byte0 [expr {($num >> 0) & 255}] set byte1 [expr {($num >> 8) & 255}] set byte2 [expr {($num >> 16) & 255}] set byte3 [expr {($num >> 24) & 255}] puts $outputfile [format "%02X" $byte0] puts $outputfile [format "%02X" $byte1] puts $outputfile [format "%02X" $byte2] puts $outputfile [format "%02X" $byte3] incr datalen 4 } close $inputfile close $outputfile return $datalen } proc generate_index_file {dstfile ebd_exists ebd_length} { if {$ebd_exists == 1} { set ebd_ptr0 [expr {128 + 532}] set ebd_ptr1 [expr {33554432 + 532}] set ebd_ptr2 [expr {67108864 + 532}] } set outputfile [open $dstfile w] set ebd0_byte0 [expr {($ebd_ptr0 >> 0) & 255}] set ebd0_byte1 [expr {($ebd_ptr0 >> 8) & 255}] set ebd0_byte2 [expr {($ebd_ptr0 >> 16) & 255}] set ebd0_byte3 [expr {($ebd_ptr0 >> 24) & 255}] puts $outputfile [format "%02X" $ebd0_byte0] puts $outputfile [format "%02X" $ebd0_byte1] puts $outputfile [format "%02X" $ebd0_byte2] puts $outputfile [format "%02X" $ebd0_byte3] set ebd1_byte0 [expr {($ebd_ptr1 >> 0) & 255}] set ebd1_byte1 [expr {($ebd_ptr1 >> 8) & 255}] set ebd1_byte2 [expr {($ebd_ptr1 >> 16) & 255}] set ebd1_byte3 [expr {($ebd_ptr1 >> 24) & 255}] puts $outputfile [format "%02X" $ebd1_byte0] puts $outputfile [format "%02X" $ebd1_byte1] puts $outputfile [format "%02X" $ebd1_byte2] puts $outputfile [format "%02X" $ebd1_byte3] set ebd2_byte0 [expr {($ebd_ptr2 >> 0) & 255}] set ebd2_byte1 [expr {($ebd_ptr2 >> 8) & 255}] set ebd2_byte2 [expr {($ebd_ptr2 >> 16) & 255}] set ebd2_byte3 [expr {($ebd_ptr2 >> 24) & 255}] puts $outputfile [format "%02X" $ebd2_byte0] puts $outputfile [format "%02X" $ebd2_byte1] puts $outputfile [format "%02X" $ebd2_byte2] puts $outputfile [format "%02X" $ebd2_byte3] for {set i 0} {$i < 116} {incr i 1} { puts $outputfile [format "%02X" 255] } close $outputfile return 0 } proc generate_vmf {dstfile indexfile ebd_exists ebd0_trim ebd1_trim ebd2_trim ebdlenght numarg} { set outputfile [open $dstfile w] puts $outputfile "@00" set inputfile [open $indexfile r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile ## 3 SLRs if { ($numarg == 9) || ($numarg == 5) } { if {$ebd_exists == 1} { set inputfile [open $ebd0_trim r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile set num_blank [expr {33554432 - ($ebdlenght +128)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } set inputfile [open $ebd1_trim r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile set num_blank [expr {33554432 - ($ebdlenght)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } set inputfile [open $ebd2_trim r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile set num_blank [expr {33554432 - ($ebdlenght)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } set num_blank [expr {33554432 - (0)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } } } ## 2 SLRs if { ($numarg == 7) || ($numarg == 4) } { if {$ebd_exists == 1} { set inputfile [open $ebd0_trim r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile set num_blank [expr {33554432 - ($ebdlenght +128)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } set inputfile [open $ebd1_trim r] while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts $outputfile $line } } close $inputfile set num_blank [expr {33554432 - ($ebdlenght)}] for {set i 0} {$i < $num_blank} {incr i 1} { puts $outputfile [format "%02X" 255] } } } close $outputfile return 0 } proc generate_bin_from_vmf {dstfile vmffile} { set inputfile [open $vmffile r] set outputfile [open $dstfile w] fconfigure $outputfile -translation binary -encoding binary gets $inputfile line while {[gets $inputfile line] >= 0} { if {[string length $line] >= 0} { puts -nonewline $outputfile [binary format c [expr "0x$line"]] } } close $inputfile close $outputfile return 0 } proc generate_mcs_from_vmf {dstfile vmffile} { set inputfile [open $vmffile r] set outputfile [open $dstfile w] gets $inputfile line set keep_reading 1 set address0 0 set address1 0 set address2 0 set address3 0 while {$keep_reading == 1} { if {$address0 == 0 && $address1 == 00} { puts -nonewline $outputfile ":02000004" puts -nonewline $outputfile [format "%02X" $address3] puts -nonewline $outputfile [format "%02X" $address2] set checksum [expr {-6 - $address3 - $address2}] set checksum [expr {$checksum & 255}] puts $outputfile [format "%02X" $checksum] } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp00 [expr "0x00$line"] } else { set temp00 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp01 [expr "0x00$line"] } else { set temp01 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp02 [expr "0x00$line"] } else { set temp02 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp03 [expr "0x00$line"] } else { set temp03 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp04 [expr "0x00$line"] } else { set temp04 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp05 [expr "0x00$line"] } else { set temp05 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp06 [expr "0x00$line"] } else { set temp06 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp07 [expr "0x00$line"] } else { set temp07 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp08 [expr "0x00$line"] } else { set temp08 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp09 [expr "0x00$line"] } else { set temp09 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0A [expr "0x00$line"] } else { set temp0A 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0B [expr "0x00$line"] } else { set temp0B 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0C [expr "0x00$line"] } else { set temp0C 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0D [expr "0x00$line"] } else { set temp0D 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0E [expr "0x00$line"] } else { set temp0E 255 set keep_reading 0 } if {[gets $inputfile line] >= 0 && $keep_reading == 1} { set temp0F [expr "0x00$line"] } else { set temp0F 255 set keep_reading 0 } puts -nonewline $outputfile ":10" puts -nonewline $outputfile [format "%02X" $address1] puts -nonewline $outputfile [format "%02X" $address0] puts -nonewline $outputfile "00" puts -nonewline $outputfile [format "%02X" $temp00] puts -nonewline $outputfile [format "%02X" $temp01] puts -nonewline $outputfile [format "%02X" $temp02] puts -nonewline $outputfile [format "%02X" $temp03] puts -nonewline $outputfile [format "%02X" $temp04] puts -nonewline $outputfile [format "%02X" $temp05] puts -nonewline $outputfile [format "%02X" $temp06] puts -nonewline $outputfile [format "%02X" $temp07] puts -nonewline $outputfile [format "%02X" $temp08] puts -nonewline $outputfile [format "%02X" $temp09] puts -nonewline $outputfile [format "%02X" $temp0A] puts -nonewline $outputfile [format "%02X" $temp0B] puts -nonewline $outputfile [format "%02X" $temp0C] puts -nonewline $outputfile [format "%02X" $temp0D] puts -nonewline $outputfile [format "%02X" $temp0E] puts -nonewline $outputfile [format "%02X" $temp0F] set checksum [expr {-16 - $address1 - $address0}] set checksum [expr {$checksum - $temp00 - $temp01 - $temp02 - $temp03}] set checksum [expr {$checksum - $temp04 - $temp05 - $temp06 - $temp07}] set checksum [expr {$checksum - $temp08 - $temp09 - $temp0A - $temp0B}] set checksum [expr {$checksum - $temp0C - $temp0D - $temp0E - $temp0F}] set checksum [expr {$checksum & 255}] puts $outputfile [format "%02X" $checksum] set address0 [expr {$address0 + 16}] if {$address0 >= 256} { set address0 0 set address1 [expr {$address1 + 1}] } if {$address1 >= 256} { set address1 0 set address2 [expr {$address2 + 1}] } if {$address2 >= 256} { set address2 0 set address3 [expr {$address3 + 1}] } } puts $outputfile ":00000001FF" close $outputfile close $inputfile return 0 } proc makedata {args} { set argc [llength $args] set argv $args puts "Xilinx UltraScale SEM data format utility starting." if {$argc != 5} { if {$argc != 4} { puts "Usage:" puts " makedata -ebd ebdfilenames outfilebase" puts " " puts "Example:" puts " makedata -ebd top0.ebd top1.ebd spi_flash" puts " " puts "EBD files are generated by write_bitstream, with tcl set_property" puts "essentialbits:yes. The outfilebase is the base name of the output" puts "file(s) that will be generated by this utility. Those files are" puts "MCS, BIN, and VMF files used for memory initialization." return } } puts " " puts "Legal number of arguments." if {$argc == 5} { puts "There are five arguments." if {[lindex $argv 0] == "-ebd"} { set ebd_exists 1 set ebd_file0 "[lindex $argv 1]" set ebd_file1 "[lindex $argv 2]" set ebd_file2 "[lindex $argv 3]" if {[file exists $ebd_file0] != 1} { puts "Specified EBD file 0 does not exist."; return } if {[file exists $ebd_file1] != 1} { puts "Specified EBD file 1 does not exist."; return } if {[file exists $ebd_file2] != 1} { puts "Specified EBD file 2 does not exist."; return } set vmf_file "[lindex $argv 4].vmf" set bin_file "[lindex $argv 4].bin" set mcs_file "[lindex $argv 4].mcs" } else { puts "Unexpected input arguments." return } } if {$argc == 4} { puts "There are four arguments." if {[lindex $argv 0] == "-ebd"} { set ebd_exists 1 set ebd_file0 "[lindex $argv 1]" set ebd_file1 "[lindex $argv 2]" if {[file exists $ebd_file0] != 1} { puts "Specified EBD file 0 does not exist."; return } if {[file exists $ebd_file1] != 1} { puts "Specified EBD file 1 does not exist."; return } set vmf_file "[lindex $argv 3].vmf" set bin_file "[lindex $argv 3].bin" set mcs_file "[lindex $argv 3].mcs" } else { puts "Unexpected input arguments." return } } puts " " ## 3 SLRs if { ($argc == 5) } { if {$ebd_exists == 1} { puts "Trimming the EBD file 0 $ebd_file0" set ebd_length [trim_and_convert_file $ebd_file0 "ebd0_trim.txt" 8] puts " Contains $ebd_length bytes" puts "Trimming the EBD file 1 $ebd_file1" set ebd_length [trim_and_convert_file $ebd_file1 "ebd1_trim.txt" 8] puts " Contains $ebd_length bytes" puts "Trimming the EBD file 2 $ebd_file2" set ebd_length [trim_and_convert_file $ebd_file2 "ebd2_trim.txt" 8] puts " Contains $ebd_length bytes" } else { set ebd_length 0 } } ## 2 SLRs if { ($argc == 4) } { if {$ebd_exists == 1} { puts "Trimming the EBD file 0 $ebd_file0" set ebd_length [trim_and_convert_file $ebd_file0 "ebd0_trim.txt" 8] puts " Contains $ebd_length bytes" puts "Trimming the EBD file 1 $ebd_file1" set ebd_length [trim_and_convert_file $ebd_file1 "ebd1_trim.txt" 8] puts " Contains $ebd_length bytes" } else { set ebd_length 0 } } puts "Generating the data index file." generate_index_file "index.txt" $ebd_exists $ebd_length puts " Contains 128 bytes" puts " " ## 3 SLRs if { ($argc == 5) } { puts "Generating the VMF file $vmf_file" generate_vmf $vmf_file index.txt $ebd_exists ebd0_trim.txt ebd1_trim.txt ebd2_trim.txt $ebd_length $argc } ## 2 SLRs if { ($argc == 4) } { puts "Generating the VMF file $vmf_file" generate_vmf $vmf_file index.txt $ebd_exists ebd0_trim.txt ebd1_trim.txt ebd1_trim.txt $ebd_length $argc } puts "Generating the BIN file $bin_file" generate_bin_from_vmf $bin_file $vmf_file puts "Generating the MCS file $mcs_file