From 086cdfea8d539893e1ef23bc414c9bbfd763ec02 Mon Sep 17 00:00:00 2001 From: Nicolas Kruse Date: Thu, 11 Sep 2025 22:22:17 +0200 Subject: [PATCH] new stencil generator added --- .gitignore | 3 +- CITATION.cff | 18 --- build_ops_obj.sh | 6 +- src/copapy/__init__.py | 19 ++- src/copapy/generate_stancils.py | 83 +++++++++++ src/copapy/stancils.c | 235 ++++++++++++++++++++++++++++++++ 6 files changed, 336 insertions(+), 28 deletions(-) delete mode 100644 CITATION.cff create mode 100644 src/copapy/generate_stancils.py create mode 100644 src/copapy/stancils.c diff --git a/.gitignore b/.gitignore index 8508223..aa7f98e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ __pycache__ .mypy_cache .pytest_cache tests/autogenerated_*.py -*test*.o \ No newline at end of file +*test*.o +/src/copapy/obj/ops*.o diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index f3770d9..0000000 --- a/CITATION.cff +++ /dev/null @@ -1,18 +0,0 @@ -cff-version: 1.2.0 -title: Gaspype -abstract: Gaspype is a performant library for thermodynamic calculations with ideal gases -authors: - - family-names: Kruse - given-names: Nicolas - orcid: "https://orcid.org/0000-0001-6758-2269" - affiliation: "German Aerospace Center (DLR)" - address: "Linder Höhe" - city: Köln -version: 1.0.1 -date-released: "2025-05-09" -#identifiers: -# - description: This is the collection of archived snapshots of all versions of Gaspype -# type: doi -# value: "" -license: MIT License -repository-code: "https://github.com/DLR-Institute-of-Future-Fuels/gaspype" \ No newline at end of file diff --git a/build_ops_obj.sh b/build_ops_obj.sh index adf3959..6b5444a 100644 --- a/build_ops_obj.sh +++ b/build_ops_obj.sh @@ -1,5 +1,7 @@ #!/bin/bash set -e - +set -v +python src/copapy/generate_stancils.py mkdir -p src/copapy/obj -gcc -c src/copapy/ops.c -o src/copapy/obj/ops_x86_64.o \ No newline at end of file +gcc -c src/copapy/stancils.c -o src/copapy/obj/stancils_x86_64.o +ls -l src/copapy/obj/*.o diff --git a/src/copapy/__init__.py b/src/copapy/__init__.py index aee2a45..4e3f95a 100644 --- a/src/copapy/__init__.py +++ b/src/copapy/__init__.py @@ -10,15 +10,17 @@ def get_var_name(var: Any, scope: dict[str, Any] = globals()) -> list[str]: def _get_c_function_definitions(code: str) -> dict[str, str]: - ret = re.findall(r".*?void\s+([a-z_1-9]*)\s*\([^\)]*?\)[^\}]*?\{[^\}]*?result_([a-z_]*)\(.*?", code, flags=re.S) + ret = re.findall(r".*?void\s+([a-z_0-9]*)\s*\([^\)]*?\)[^\}]*?\{[^\}]*?result_([a-z_]*)\(.*?", code, flags=re.S) return {r[0]: r[1] for r in ret} -_ccode = pkgutil.get_data(__name__, 'ops.c') +_ccode = pkgutil.get_data(__name__, 'stancils.c') assert _ccode is not None _function_definitions = _get_c_function_definitions(_ccode.decode('utf-8')) +print(_function_definitions) + class Node: def __init__(self): self.args: list[Net] = [] @@ -105,7 +107,7 @@ def _add_op(op: str, args: list[Any], commutative: bool = False) -> Net: if typed_op not in _function_definitions: raise ValueError(f"Unsupported operand type(s) for {op}: {' and '.join([a.dtype for a in arg_nets])}") - result_type = _function_definitions[typed_op] + result_type = _function_definitions[typed_op].split('_')[0] result_net = Net(result_type, Op(typed_op, arg_nets)) @@ -224,7 +226,7 @@ def add_read_ops(node_list: list[Node]) -> Generator[tuple[Net | None, Node], No Returns: Yields a tuples of a net and a operation. The net is the result net from the returned operation""" - registers: list[None | Net] = [None] * 16 + registers: list[None | Net] = [None] * 2 net_lookup = {net.source: net for node in node_list for net in node.args} @@ -234,7 +236,9 @@ def add_read_ops(node_list: list[Node]) -> Generator[tuple[Net | None, Node], No if net != registers[i]: #if net in registers: # print('x swap registers') - new_node = Op('read_reg' + str(i) + '_' + net.dtype, []) + type_list = ['int' if r is None else r.dtype for r in registers] + print(type_list) + new_node = Op('read_reg' + str(i) + '_' + '_'.join(type_list), []) yield net, new_node registers[i] = net @@ -273,7 +277,7 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w extended_output_ops = list(add_write_ops(output_ops, const_list)) - obj_file: str = 'src/copapy/obj/test4_o0.o' + obj_file: str = 'src/copapy/obj/stancils_x86_64.o' elf = pelfy.open_elf_file(obj_file) dw = binw.data_writer(elf.byteorder) @@ -305,7 +309,8 @@ def compile_to_instruction_list(end_nodes: Iterable[Node] | Node) -> binw.data_w print(list(prototype_functions.keys())) for net, node in extended_output_ops: if node.name in prototype_functions: - print(prototype_functions[node.name]) + #print(prototype_functions[node.name]) + pass else: print(f"- Warning: {node.name} prototype not found") print('-----') diff --git a/src/copapy/generate_stancils.py b/src/copapy/generate_stancils.py new file mode 100644 index 0000000..4f58c28 --- /dev/null +++ b/src/copapy/generate_stancils.py @@ -0,0 +1,83 @@ +from typing import Generator + + +op_signs = {'add': '+', 'sub': '-', 'mul': '*', 'div': '/'} + +def get_op_code(op: str, type1: str, type2: str, type_out: str): + return f""" + void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + asm volatile (".long 0xF17ECAFE"); + result_{type_out}_{type2}(arg1 {op_signs[op]} arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + }} + """ + +def get_result_stubs(type1: str, type2: str): + return f""" + void result_{type1}_{type2}({type1} arg1, {type2} arg2); + """ + +def get_read_reg0_code(type1: str, type2: str, type_out: str): + return f""" + void read_reg0_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + asm volatile (".long 0xF17ECAFE"); + result_{type_out}_{type2}(dummy_{type_out}, arg2); + asm volatile (".long 0xF27ECAFE"); + }} + """ + +def get_read_reg1_code(type1: str, type2: str, type_out: str): + return f""" + void read_reg1_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + asm volatile (".long 0xF17ECAFE"); + result_{type1}_{type_out}(arg1, dummy_{type_out}); + asm volatile (".long 0xF27ECAFE"); + }} + """ + +def get_write_code(type1: str, type2: str): + return f""" + void write_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + asm volatile (".long 0xF17ECAFE"); + dummy_{type1} = arg1; + result_{type1}_{type2}(arg1, arg2); + asm volatile (".long 0xF27ECAFE"); + }} + """ + +def permutate(*lists: list[str]) -> Generator[list[str], None, None]: + if len(lists) == 0: + yield [] + return + first, *rest = lists + for item in first: + for items in permutate(*rest): + yield [item, *items] + +if __name__ == "__main__": + types = ['int', 'float'] + ops = ['add', 'sub', 'mul', 'div'] + + code = """ + // Auto-generated stancils for copapy + // Do not edit manually + + volatile int dummy_int = 1337; + volatile float dummy_float = 1337; + """ + for t1, t2 in permutate(types, types): + code += get_result_stubs(t1, t2) + + for op, t1, t2 in permutate(ops, types, types): + t_out = t1 if t1 == t2 else 'float' + code += get_op_code(op, t1, t2, t_out) + + for t1, t2, t_out in permutate(types, types, types): + code += get_read_reg0_code(t1, t2, t_out) + code += get_read_reg1_code(t1, t2, t_out) + + for t1, t2 in permutate(types, types): + code += get_write_code(t1, t2) + + with open('src/copapy/stancils.c', 'w') as f: + f.write(code) diff --git a/src/copapy/stancils.c b/src/copapy/stancils.c new file mode 100644 index 0000000..49a7ef0 --- /dev/null +++ b/src/copapy/stancils.c @@ -0,0 +1,235 @@ + + // Auto-generated stancils for copapy + // Do not edit manually + + volatile int dummy_int = 1337; + volatile float dummy_float = 1337; + + void result_int_int(int arg1, int arg2); + + void result_int_float(int arg1, float arg2); + + void result_float_int(float arg1, int arg2); + + void result_float_float(float arg1, float arg2); + + void add_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1 + arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void add_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 + arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void add_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1 + arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void add_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 + arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void sub_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1 - arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void sub_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 - arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void sub_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1 - arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void sub_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 - arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void mul_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1 * arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void mul_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 * arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void mul_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1 * arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void mul_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 * arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void div_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1 / arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void div_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 / arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void div_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1 / arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void div_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1 / arg2, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(dummy_int, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1, dummy_int); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(dummy_float, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_float(arg1, dummy_float); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_float(dummy_int, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(arg1, dummy_int); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(dummy_float, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_float(arg1, dummy_float); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_int(dummy_int, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1, dummy_int); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(dummy_float, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1, dummy_float); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_int_float(dummy_int, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_int(arg1, dummy_int); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg0_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(dummy_float, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void read_reg1_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + result_float_float(arg1, dummy_float); + asm volatile (".long 0xF27ECAFE"); + } + + void write_int_int(int arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + dummy_int = arg1; + result_int_int(arg1, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void write_int_float(int arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + dummy_int = arg1; + result_int_float(arg1, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void write_float_int(float arg1, int arg2) { + asm volatile (".long 0xF17ECAFE"); + dummy_float = arg1; + result_float_int(arg1, arg2); + asm volatile (".long 0xF27ECAFE"); + } + + void write_float_float(float arg1, float arg2) { + asm volatile (".long 0xF17ECAFE"); + dummy_float = arg1; + result_float_float(arg1, arg2); + asm volatile (".long 0xF27ECAFE"); + } + \ No newline at end of file