| COPYRIGHT = """\ |
| /* |
| * Copyright 2021 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| """ |
| |
| import argparse |
| import os |
| |
| from grl_parser import parse_grl_file |
| from mako.template import Template |
| |
| TEMPLATE_H = Template(COPYRIGHT + """ |
| /* This file generated from ${filename}, don't edit directly. */ |
| |
| #ifndef GRL_CL_KERNEL_H |
| #define GRL_CL_KERNEL_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include "genxml/gen_macros.h" |
| #include "compiler/brw_kernel.h" |
| |
| enum grl_cl_kernel { |
| % for k in kernels: |
| GRL_CL_KERNEL_${k.upper()}, |
| % endfor |
| GRL_CL_KERNEL_MAX, |
| }; |
| |
| const char *grl_cl_kernel_name(enum grl_cl_kernel kernel); |
| |
| const char *genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id); |
| |
| void genX(grl_get_cl_kernel)(struct brw_kernel *kernel, enum grl_cl_kernel id); |
| |
| #ifdef __cplusplus |
| } /* extern "C" */ |
| #endif |
| |
| #endif /* INTEL_GRL_H */ |
| """, output_encoding='utf-8') |
| |
| TEMPLATE_C = Template(COPYRIGHT + """ |
| /* This file generated from ${filename}, don't edit directly. */ |
| |
| #include "grl_cl_kernel.h" |
| |
| % for k in kernels: |
| #include "${prefix}_${k}.h" |
| % endfor |
| |
| const char * |
| grl_cl_kernel_name(enum grl_cl_kernel kernel) |
| { |
| switch (kernel) { |
| % for k in kernels: |
| case GRL_CL_KERNEL_${k.upper()}: return "${k}"; |
| % endfor |
| default: return "unknown"; |
| } |
| } |
| |
| const char * |
| genX(grl_get_cl_kernel_sha1)(enum grl_cl_kernel id) |
| { |
| switch (id) { |
| % for k in kernels: |
| case GRL_CL_KERNEL_${k.upper()}: return ${prefix}_${k}_sha1; |
| % endfor |
| default: |
| unreachable("Invalid GRL kernel enum"); |
| } |
| }; |
| |
| void |
| ${prefix}_grl_get_cl_kernel(struct brw_kernel *kernel, enum grl_cl_kernel id) |
| { |
| switch (id) { |
| % for k in kernels: |
| case GRL_CL_KERNEL_${k.upper()}: |
| *kernel = ${prefix}_${k}; |
| break; |
| % endfor |
| default: |
| unreachable("Invalid GRL kernel enum"); |
| } |
| } |
| """, output_encoding='utf-8') |
| |
| def get_libraries_files(kernel_module): |
| lib_files = [] |
| for item in kernel_module[3]: |
| if item[0] != 'library': |
| continue |
| default_file = None |
| fallback_file = None |
| path_directory = None |
| for props in item[2]: |
| if props[0] == 'fallback': |
| fallback_file = props[1] |
| elif props[0] == 'default': |
| default_file = props[1] |
| elif props[0] == 'path': |
| path_directory = props[1] |
| assert path_directory |
| assert default_file or fallback_file |
| if fallback_file: |
| lib_files.append(os.path.join(path_directory, fallback_file)) |
| else: |
| lib_files.append(os.path.join(path_directory, default_file)) |
| return lib_files |
| |
| def add_kernels(kernels, cl_file, entrypoint, libs): |
| assert cl_file.endswith('.cl') |
| for lib_file in libs: |
| assert lib_file.endswith('.cl') |
| kernels.append((cl_file, entrypoint, ','.join(libs))) |
| |
| def get_kernels(grl_nodes): |
| kernels = [] |
| for item in grl_nodes: |
| assert isinstance(item, tuple) |
| if item[0] == 'kernel': |
| ann = item[2] |
| add_kernels(kernels, ann['source'], ann['kernelFunction'], []) |
| elif item[0] == 'kernel-module': |
| cl_file = item[2] |
| libfiles = get_libraries_files(item) |
| for kernel_def in item[3]: |
| if kernel_def[0] == 'kernel': |
| ann = kernel_def[2] |
| add_kernels(kernels, cl_file, ann['kernelFunction'], libfiles) |
| return kernels |
| |
| def parse_libraries(filenames): |
| libraries = {} |
| for fname in filenames: |
| lib_package = parse_grl_file(fname, []) |
| for lib in lib_package: |
| assert lib[0] == 'library' |
| # Add the directory of the library so that CL files can be found. |
| lib[2].append(('path', os.path.dirname(fname))) |
| libraries[lib[1]] = lib |
| return libraries |
| |
| def main(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--out-c', help='Output C file') |
| parser.add_argument('--out-h', help='Output H file') |
| parser.add_argument('--ls-kernels', action='store_const', const=True, |
| help='List all openCL kernels') |
| parser.add_argument('--prefix', help='Prefix') |
| parser.add_argument('--library', dest='libraries', action='append', |
| default=[], help='Libraries to include') |
| parser.add_argument('files', type=str, nargs='*', help='GRL files') |
| args = parser.parse_args() |
| |
| libraries = parse_libraries(args.libraries) |
| |
| kernels = [] |
| for fname in args.files: |
| kernels += get_kernels(parse_grl_file(fname, libraries)) |
| |
| # Make the list of kernels unique and sorted |
| kernels = sorted(list(set(kernels))) |
| |
| if args.ls_kernels: |
| for cl_file, entrypoint, libs in kernels: |
| if not os.path.isabs(cl_file): |
| cl_file = os.path.join(os.path.dirname(fname), cl_file) |
| print('{}:{}:{}'.format(cl_file, entrypoint, libs)) |
| |
| kernel_c_names = [] |
| for cl_file, entrypoint, libs in kernels: |
| cl_file = os.path.splitext(cl_file)[0] |
| cl_file_name = cl_file.replace('/', '_') |
| kernel_c_names.append('_'.join([cl_file_name, entrypoint])) |
| |
| try: |
| if args.out_h: |
| with open(args.out_h, 'wb') as f: |
| f.write(TEMPLATE_H.render(kernels=kernel_c_names, |
| filename=os.path.basename(__file__))) |
| |
| if args.out_c: |
| with open(args.out_c, 'wb') as f: |
| f.write(TEMPLATE_C.render(kernels=kernel_c_names, |
| prefix=args.prefix, |
| filename=os.path.basename(__file__))) |
| except Exception: |
| # In the event there's an error, this imports some helpers from mako |
| # to print a useful stack trace and prints it, then exits with |
| # status 1, if python is run with debug; otherwise it just raises |
| # the exception |
| if __debug__: |
| import sys |
| from mako import exceptions |
| sys.stderr.write(exceptions.text_error_template().render() + '\n') |
| sys.exit(1) |
| raise |
| |
| if __name__ == '__main__': |
| main() |