1COPYRIGHT = """\ 2/* 3 * Copyright 2021 Intel Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25""" 26 27import argparse 28import os 29 30from grl_parser import parse_grl_file 31from mako.template import Template 32 33TEMPLATE_H = Template(COPYRIGHT + """ 34/* This file generated from ${filename}, don't edit directly. */ 35 36#ifndef GRL_CL_KERNEL_H 37#define GRL_CL_KERNEL_H 38 39#include "genxml/gen_macros.h" 40#include "compiler/brw_kernel.h" 41 42#ifdef __cplusplus 43extern "C" { 44#endif 45 46enum grl_cl_kernel { 47% for k in kernels: 48 GRL_CL_KERNEL_${k.upper()}, 49% endfor 50 GRL_CL_KERNEL_MAX, 51}; 52 53const char *genX(grl_cl_kernel_name)(enum grl_cl_kernel kernel); 54 55const char *genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id); 56 57void genX(grl_get_cl_kernel)(struct brw_kernel *kernel, enum grl_cl_kernel id); 58 59#ifdef __cplusplus 60} /* extern "C" */ 61#endif 62 63#endif /* INTEL_GRL_H */ 64""") 65 66TEMPLATE_C = Template(COPYRIGHT + """ 67/* This file generated from ${filename}, don't edit directly. */ 68 69#include "grl_cl_kernel.h" 70 71% for k in kernels: 72#include "${prefix}_${k}.h" 73% endfor 74 75const char * 76genX(grl_cl_kernel_name)(enum grl_cl_kernel kernel) 77{ 78 switch (kernel) { 79% for k in kernels: 80 case GRL_CL_KERNEL_${k.upper()}: return "${k}"; 81% endfor 82 default: return "unknown"; 83 } 84} 85 86const char * 87genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id) 88{ 89 switch (id) { 90% for k in kernels: 91 case GRL_CL_KERNEL_${k.upper()}: return ${prefix}_${k}_sha1; 92% endfor 93 default: 94 unreachable("Invalid GRL kernel enum"); 95 } 96}; 97 98void 99${prefix}_grl_get_cl_kernel(struct brw_kernel *kernel, enum grl_cl_kernel id) 100{ 101 switch (id) { 102% for k in kernels: 103 case GRL_CL_KERNEL_${k.upper()}: 104 *kernel = ${prefix}_${k}; 105 break; 106% endfor 107 default: 108 unreachable("Invalid GRL kernel enum"); 109 } 110} 111""") 112 113def get_libraries_files(kernel_module): 114 lib_files = [] 115 for item in kernel_module[3]: 116 if item[0] != 'library': 117 continue 118 default_file = None 119 fallback_file = None 120 path_directory = None 121 for props in item[2]: 122 if props[0] == 'fallback': 123 fallback_file = props[1] 124 elif props[0] == 'default': 125 default_file = props[1] 126 elif props[0] == 'path': 127 path_directory = props[1] 128 assert path_directory 129 assert default_file or fallback_file 130 if fallback_file: 131 lib_files.append(os.path.join(path_directory, fallback_file)) 132 else: 133 lib_files.append(os.path.join(path_directory, default_file)) 134 return lib_files 135 136def add_kernels(kernels, cl_file, entrypoint, libs): 137 assert cl_file.endswith('.cl') 138 for lib_file in libs: 139 assert lib_file.endswith('.cl') 140 kernels.append((cl_file, entrypoint, ','.join(libs))) 141 142def get_kernels(grl_nodes): 143 kernels = [] 144 for item in grl_nodes: 145 assert isinstance(item, tuple) 146 if item[0] == 'kernel': 147 ann = item[2] 148 add_kernels(kernels, ann['source'], ann['kernelFunction'], []) 149 elif item[0] == 'kernel-module': 150 cl_file = item[2] 151 libfiles = get_libraries_files(item) 152 for kernel_def in item[3]: 153 if kernel_def[0] == 'kernel': 154 ann = kernel_def[2] 155 add_kernels(kernels, cl_file, ann['kernelFunction'], libfiles) 156 return kernels 157 158def parse_libraries(filenames): 159 libraries = {} 160 for fname in filenames: 161 lib_package = parse_grl_file(fname, []) 162 for lib in lib_package: 163 assert lib[0] == 'library' 164 # Add the directory of the library so that CL files can be found. 165 lib[2].append(('path', os.path.dirname(fname))) 166 libraries[lib[1]] = lib 167 return libraries 168 169def main(): 170 parser = argparse.ArgumentParser() 171 parser.add_argument('--out-c', help='Output C file') 172 parser.add_argument('--out-h', help='Output H file') 173 parser.add_argument('--ls-kernels', action='store_const', const=True, 174 help='List all openCL kernels') 175 parser.add_argument('--prefix', help='Prefix') 176 parser.add_argument('--library', dest='libraries', action='append', 177 default=[], help='Libraries to include') 178 parser.add_argument('files', type=str, nargs='*', help='GRL files') 179 args = parser.parse_args() 180 181 libraries = parse_libraries(args.libraries) 182 183 kernels = [] 184 for fname in args.files: 185 kernels += get_kernels(parse_grl_file(fname, libraries)) 186 187 # Make the list of kernels unique and sorted 188 kernels = sorted(list(set(kernels))) 189 190 if args.ls_kernels: 191 for cl_file, entrypoint, libs in kernels: 192 if not os.path.isabs(cl_file): 193 cl_file = os.path.join(os.path.dirname(fname), cl_file) 194 print('{}:{}:{}'.format(cl_file, entrypoint, libs)) 195 196 kernel_c_names = [] 197 for cl_file, entrypoint, libs in kernels: 198 cl_file = os.path.splitext(cl_file)[0] 199 cl_file_name = cl_file.replace('/', '_') 200 kernel_c_names.append('_'.join([cl_file_name, entrypoint])) 201 202 try: 203 if args.out_h: 204 with open(args.out_h, 'w', encoding='utf-8') as f: 205 f.write(TEMPLATE_H.render(kernels=kernel_c_names, 206 filename=os.path.basename(__file__))) 207 208 if args.out_c: 209 with open(args.out_c, 'w', encoding='utf-8') as f: 210 f.write(TEMPLATE_C.render(kernels=kernel_c_names, 211 prefix=args.prefix, 212 filename=os.path.basename(__file__))) 213 except Exception: 214 # In the event there's an error, this imports some helpers from mako 215 # to print a useful stack trace and prints it, then exits with 216 # status 1, if python is run with debug; otherwise it just raises 217 # the exception 218 if __debug__: 219 import sys 220 from mako import exceptions 221 sys.stderr.write(exceptions.text_error_template().render() + '\n') 222 sys.exit(1) 223 raise 224 225if __name__ == '__main__': 226 main() 227