1import os,shutil 2import sys 3import argparse 4 5import struct 6import os 7from sys import platform 8 9# Usage: 10# merge.py -o out_file in_file [in_file...] 11# 12# Description: 13# This script merges N kernels given in arguments (in_file...) to the common kernel (out_file) according 14# to the following output format: 15# 16# | DW0: kernel_count | DW1: offset_of_kernel_1 | DW1: offset_of_kernel_2 | ... | DW15: offset_of_kernel_15 | 17# | kernel_1 (size aligned to 64 bytes) | 18# | kernel_2 (size aligned to 64 bytes) | 19# | ... | 20# | kernel_15 (size aligned to 64 bytes) | 21# | padding 128 bytes | 22# 23# Limitations: 24# - No more than 15 kernels are being merged 25 26parser = argparse.ArgumentParser() 27parser.add_argument("-o", "--output", dest="out_file", required=True, 28 help="merged output kernel file name") 29parser.add_argument('dat_files', metavar='IN_FILE', type=str, nargs='+', 30 help='list of input kernels to merge into common kernel (.dat files, order is important)') 31args = parser.parse_args() 32 33removeList = [] 34for filename in args.dat_files: 35 print("fileName: " + filename) 36 if(not os.path.exists(filename)): 37 print("File %s doesn't exist!" % filename) 38 removeList.append(filename) 39for filename in removeList: 40 args.dat_files.remove(filename) 41 42n_dats = len(args.dat_files) 43if n_dats > 15: 44 raise Exception("Can't merge more than 15 files") 45 46offset = [0 for i in range(64)] 47padding = [0 for i in range(64)] 48 49# offset of the first kernel (first 64 bytes are header for combined kernel) 50offset[0] = 64 51# program offset for each kernel in the header of combined kernel 52for i in range(n_dats): 53 count = offset[i] + os.path.getsize(args.dat_files[i]) 54 next_offset = ((count + 63) >> 6) << 6 # align next kernel at 64-bytes 55 padding[i] = next_offset - count 56 if (i != n_dats-1): 57 offset[i+1] = next_offset 58 59output = open(args.out_file, 'wb') 60 61# total number of kernels we are going to merge 62bytes = struct.pack('i', n_dats) 63output.write(bytes) 64 65# write offsets 66for i in range(n_dats): 67 bytes = struct.pack('i', offset[i]) 68 output.write(bytes) 69 70# zero fill for the rest of the header, totally: 71# 64 bytes header - 4*number_of_kernels - 4 bytes for number of kernels 72zerofill = chr(0)*(64 - 4 - (n_dats << 2)) 73output.write(zerofill.encode(encoding = "utf-8")) 74 75# write combined kernel, each child kernel is 64 bytes aligned 76for i in range(n_dats): 77 fileobj = open(args.dat_files[i], 'rb') 78 while 1: 79 filebytes = fileobj.read() 80 if not filebytes: 81 zerofill = chr(0)*padding[i] 82 output.write(zerofill.encode(encoding = "utf-8")) 83 break 84 output.write(filebytes) 85 fileobj.close() 86 87# padding 128 bytes at the end of combined kernel which is required by HW 88zerofill = chr(0)*128 89output.write(zerofill.encode(encoding = "utf-8")) 90 91output.close() 92print ("Completed kernel merge") 93