Files
rocm-systems/tools/generator.py
T
gabrpham 8bc4abc88b Corrected partition changes in header and wrapper
Signed-off-by: gabrpham <Gabriel.Pham@amd.com>
Change-Id: Iafd7de8f08924873da841ee6eca62100a17b2b6c
2024-09-20 17:01:55 -05:00

211 righe
9.3 KiB
Python

#
# Copyright (C) 2024 Advanced Micro Devices. All rights reserved.
#
# 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS 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 os
import argparse
import tempfile
import shutil
import platform
from subprocess import run, PIPE
from ctypeslib.clang2py import main as clangToPy
HEADER = \
"""
#
# Copyright (C) 2024 Advanced Micro Devices. All rights reserved.
#
# 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS 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 os
"""
def parseArgument():
parser = argparse.ArgumentParser(description="parse input arguments")
parser.add_argument('-o','--output', type=str, required=True,
help='The output file name')
parser.add_argument('-i','--input', type=str, required=True,
help='The input file name')
parser.add_argument('-l', '--library', type=str, required=True,
help='Loading dynamic link libraries')
parser.add_argument('-e', '--extra-args', type=str, required=False,
help='Parse extra arguments to clang')
args = vars(parser.parse_args())
return args['output'], args['input'], args['library'], args['extra_args']
def replace_line(full_path_file_name, string_to_replace, new_string):
"""
Replaces a specific string in a file with a new string.
Args:
full_path_file_name (str): The full path of the file to modify.
string_to_replace (str): The string to be replaced.
new_string (str): The new string to replace the old string with.
Returns:
None
"""
fh, abs_path = tempfile.mkstemp()
with os.fdopen(fh, 'w') as new_file:
with open(full_path_file_name, 'r+', encoding='UTF-8') as old_file:
for line in old_file:
new_file.write(line.replace(string_to_replace, new_string))
shutil.copymode(full_path_file_name, abs_path)
os.remove(full_path_file_name)
shutil.move(abs_path, full_path_file_name)
def write_header(full_path_file_name):
fh, abs_path = tempfile.mkstemp()
with os.fdopen(fh, 'w') as new_file:
new_file.write(HEADER)
with open(full_path_file_name, 'r+', encoding='UTF-8') as old_file:
for line in old_file:
new_file.write(line)
shutil.copymode(full_path_file_name, abs_path)
os.remove(full_path_file_name)
shutil.move(abs_path, full_path_file_name)
def main():
output_file, input_file, library, clang_extra_args = parseArgument()
# make args string easy to append
if clang_extra_args is None:
clang_extra_args = ""
else:
clang_extra_args = " " + clang_extra_args
library_name = os.path.basename(library)
clang_include_dir = \
run(["clang", "--print-resource-dir"], stdout=PIPE, stderr=PIPE, encoding="utf-8").stdout.strip()
os_platform = platform.system()
if os_platform == "Windows":
clang_include_dir += "\\include"
if "Program Files(x86)" in clang_include_dir:
clang_include_dir = clang_include_dir.replace("Program Files(x86)", "Progra~2")
elif "Program Files" in clang_include_dir:
clang_include_dir = clang_include_dir.replace("Program Files", "Progra~1")
arguments = [input_file, "-o", output_file]
line_to_replace = "_libraries['FIXME_STUB'] = FunctionFactoryStub() # ctypes.CDLL('FIXME_STUB')"
new_line = "_libraries['FIXME_STUB'] = ctypes.CDLL('{}')".format(library_name)
elif os_platform == "Linux":
clang_include_dir += "/include"
arguments = [input_file, "-o", output_file, "-l", library]
library_path = os.path.join(os.path.dirname(__file__), library)
line_to_replace = "_libraries['{}'] = ctypes.CDLL('{}')".format(library_name, library_path)
new_line = f"""from pathlib import Path
libamd_smi_parent_dir = Path(__file__).resolve().parent / "{library_name}"
libamd_smi_cwd = Path.cwd() / "{library_name}"
try:
if libamd_smi_parent_dir.is_file():
# try to fall back to parent directory
_libraries['{library_name}'] = ctypes.CDLL(libamd_smi_parent_dir)
else:
# lastly - search in current working directory
_libraries['{library_name}'] = ctypes.CDLL(libamd_smi_cwd)
except OSError as error:
print(error)
print("Unable to find amdsmi library try installing amd-smi-lib from your package manager")"""
else:
print("Unknown operating system. It is only supporing Linux and Windows.")
return
arguments.append("--clang-args=-I" + clang_include_dir + clang_extra_args)
clangToPy(arguments)
write_header(output_file)
replace_line(output_file, line_to_replace, new_line)
# Custom handling for anonymous struct within amdsmi_bdf_t in Linux
if os_platform == "Linux":
# Get line number for anonymous error in struct_amdsmi_bdf_t
reference_line = "uint64_t function_number :"
line_number = -1
with open(input_file, 'r') as file:
for input_file_line_number, line in enumerate(file, 1):
if reference_line in line:
line_number = input_file_line_number - 1 # Anonymous line will error on the line before this
break
if line_number == -1:
print("Could not find reference line in amdsmi.h for amdsmi_bdf_t struct. Skipping anonymous struct replacement.")
else:
print(f"Found reference line in amdsmi.h for amdsmi_bdf_t struct at line {line_number}")
union_anon_line = "union_amdsmi_bdf_t._anonymous_ = ('_0',)"
replace_line(output_file, union_anon_line, "")
internal_union_anon_line = f"('_0', struct_struct (anonymous at amdsmi.h:{line_number}:3))"
internal_union_struct_line = "('struct_amdsmi_bdf_t', struct_amdsmi_bdf_t)"
replace_line(output_file, internal_union_anon_line, internal_union_struct_line)
struct_anon_line = f"struct_struct (anonymous at amdsmi.h:{line_number}:3)"
struct_amdsmi_bdf_t_line = "struct_amdsmi_bdf_t"
replace_line(output_file, struct_anon_line, struct_amdsmi_bdf_t_line)
struct_anon_all_line = "'struct_struct (anonymous at"
struct_amdsmi_bdf_t_line = "'struct_amdsmi_bdf_t',"
replace_line(output_file, struct_anon_all_line, struct_amdsmi_bdf_t_line)
struct_anon_all_line = ", 'struct_struct"
replace_line(output_file, struct_anon_all_line, ",")
struct_anon_all_line = "(anonymous at "
struct_amdsmi_bdf_t_line = "'struct_amdsmi_bdf_t',"
replace_line(output_file, struct_anon_all_line, struct_amdsmi_bdf_t_line)
struct_anon_all_line_to_remove = f"amdsmi.h:{line_number}:3)', "
replace_line(output_file, struct_anon_all_line_to_remove, "")
# Custom handling to ensure amdsmi_get_utilization_count doesn't multiply the struct by 0
print(f"Replacing amdsmi_get_utilization_count line in {output_file}")
utilization_count_line_bad = "amdsmi_get_utilization_count.argtypes = [amdsmi_processor_handle, struct_amdsmi_utilization_counter_t * 0, uint32_t, ctypes.POINTER(ctypes.c_uint64)]"
utilization_count_line_good = "amdsmi_get_utilization_count.argtypes = [amdsmi_processor_handle, ctypes.POINTER(struct_amdsmi_utilization_counter_t), uint32_t, ctypes.POINTER(ctypes.c_uint64)]"
replace_line(output_file, utilization_count_line_bad, utilization_count_line_good)
if __name__ == "__main__":
main()