From b5e6130eb87f41f4c92cc4c3ab014bd86884f9f2 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 14 Oct 2025 22:59:51 +0200 Subject: [PATCH] patching of subfunction fixed and types for // aligned to python standard --- src/copapy/__init__.py | 15 ++++++++------- src/coparun/runmem.c | 2 +- tests/test_compile.py | 10 +++++----- tests/test_ops.py | 16 ++++++---------- tools/extract_code.py | 2 +- tools/generate_stencils.py | 17 ++++++++++++----- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/copapy/__init__.py b/src/copapy/__init__.py index df94ebb..395d82e 100644 --- a/src/copapy/__init__.py +++ b/src/copapy/__init__.py @@ -143,7 +143,7 @@ def _add_op(op: str, args: list[Any], commutative: bool = False) -> Net: if typed_op not in generic_sdb.stencil_definitions: raise ValueError(f"Unsupported operand type(s) for {op}: {' and '.join([a.dtype for a in arg_nets])}") - if op in {'eq', 'ne', 'ge'}: + if op in {'eq', 'ne', 'gt'}: result_type = 'bool' else: result_type = generic_sdb.stencil_definitions[typed_op].split('_')[0] @@ -411,7 +411,7 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database # Prepare program code and relocations object_addr_lookup = {net: offs for net, offs, _ in variable_mem_layout} data_list: list[bytes] = [] - patch_list: list[tuple[int, int, int]] = [] + patch_list: list[tuple[int, int, int, binw.Command]] = [] offset = aux_function_lengths # offset in generated code chunk # assemble stencils to main program @@ -429,13 +429,14 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database if patch.target_symbol_info == 'STT_OBJECT': assert associated_net, f"Relocation found but no net defined for operation {node.name}" addr = object_addr_lookup[associated_net] + patch_value = addr + patch.addend - (offset + patch.addr) + patch_list.append((patch.type.value, offset + patch.addr, patch_value, binw.Command.PATCH_OBJECT)) elif patch.target_symbol_info == 'STT_FUNC': addr = aux_func_addr_lookup[patch.target_symbol_name] + patch_value = addr + patch.addend - (offset + patch.addr) + patch_list.append((patch.type.value, offset + patch.addr, patch_value, binw.Command.PATCH_FUNC)) else: raise ValueError(f"Unsupported: {node.name} {patch.target_symbol_info} {patch.target_symbol_name}") - - patch_value = addr + patch.addend - (offset + patch.addr) - patch_list.append((patch.type.value, offset + patch.addr, patch_value)) offset += len(data) @@ -462,8 +463,8 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database dw.write_bytes(b''.join(data_list)) # write relocations - for patch_type, patch_addr, addr in patch_list: - dw.write_com(binw.Command.PATCH_OBJECT) + for patch_type, patch_addr, addr, patch_command in patch_list: + dw.write_com(patch_command) dw.write_int(patch_addr) dw.write_int(patch_type) dw.write_int(addr, signed=True) diff --git a/src/coparun/runmem.c b/src/coparun/runmem.c index 1860e59..dce7b6b 100644 --- a/src/coparun/runmem.c +++ b/src/coparun/runmem.c @@ -113,7 +113,7 @@ int parse_commands(uint8_t *bytes) { break; case RUN_PROG: - printf("RUN_PROG"); + printf("RUN_PROG\n"); int ret = entr_point(); printf("Return value: %i\n", ret); break; diff --git a/tests/test_compile.py b/tests/test_compile.py index 2b5f4dc..e05500c 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -6,10 +6,10 @@ from copapy import binwrite def run_command(command: list[str], encoding: str = 'utf8') -> str: - process = subprocess.Popen(command, stdout=subprocess.PIPE) + process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate() - assert error is None, f"Error occurred: {error.decode(encoding)}" + assert not error, f"\n -Error occurred: {error.decode(encoding)}\n -Output: {output.decode(encoding)}" return output.decode(encoding) @@ -35,7 +35,7 @@ def test_example(): def function(c1, c2): - i1 = c1 * 3.3 + 5 + i1 = c1 // 3.3 + 5 i2 = c2 * 5 + c1 #r1 = i1 + i2 * 55 / 4 r1 = i1 + i2 * 55 / 4 @@ -57,7 +57,6 @@ def test_compile(): # run program command il.write_com(binwrite.Command.RUN_PROG) - il.write_int(0) il.write_com(binwrite.Command.READ_DATA) il.write_int(0) @@ -71,8 +70,9 @@ def test_compile(): il.to_file('bin/test.copapy') result = run_command(['bin/coparun', 'bin/test.copapy']) - print('* Output from runner:') + print('* Output from runner:\n--') print(result) + print('--') assert 'Return value: 1' in result diff --git a/tests/test_ops.py b/tests/test_ops.py index 5da0319..b424a45 100644 --- a/tests/test_ops.py +++ b/tests/test_ops.py @@ -25,29 +25,25 @@ def function5(c1): def test_compile(): - c1 = CPVariable(9) - c2 = CPVariable(1.111) - c3 = CPVariable(False) + c_i = CPVariable(9) + c_f = CPVariable(1.111) + c_b = CPVariable(True) - #ret_test = function1(c1) + function1(c2) + function2(c1) + function2(c2) + function3(c3) + function4(c1) + function5(c3) + [CPVariable(9) % 2] - #ret_ref = function1(9) + function1(1.111) + function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] - - ret_test = [c1 / 4] - ret_ref = [9 / 4] + ret_test = function1(c_i) + function1(c_f) #+ function2(c_i) + function2(c_f) + function3(c_i) + function4(c_i) + function5(c_b) + [CPVariable(9) % 2] + ret_ref = function1(9) + function1(1.111) #+ function2(9) + function2(1.111) + function3(9) + function4(9) + function5(True) + [9 % 2] print(ret_test) tg = Target() print('* compile and copy ...') tg.compile(ret_test) - #time.sleep(5) print('* run and copy ...') tg.run() print('* finished') for test, ref in zip(ret_test, ret_ref): val = tg.read_value(test) - print('+', val, ref) + #print('+', val, ref, test.dtype) for t in [int, float, bool]: assert isinstance(val, t) == isinstance(ref, t), f"Result type does not match for {val} and {ref}" assert val == approx(ref, 1e-5), f"Result does not match: {val} and reference: {ref}" diff --git a/tools/extract_code.py b/tools/extract_code.py index c098ed3..ab7d4ad 100644 --- a/tools/extract_code.py +++ b/tools/extract_code.py @@ -6,7 +6,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("input_file", type=str, help="Input file path with copapy commands") parser.add_argument("output_file", type=str, help="Output file with patched code") - parser.add_argument("--data_section_offset", type=int, default=0x2000, help="Offset for data relative to code section") + parser.add_argument("--data_section_offset", type=int, default=0x3000, help="Offset for data relative to code section") parser.add_argument("--byteorder", type=str, choices=['little', 'big'], default='little', help="Select byteorder") args = parser.parse_args() diff --git a/tools/generate_stencils.py b/tools/generate_stencils.py index 94520e1..0d4a6bf 100644 --- a/tools/generate_stencils.py +++ b/tools/generate_stencils.py @@ -49,11 +49,18 @@ def get_op_code_float(op: str, type1: str, type2: str) -> str: def get_floordiv(op: str, type1: str, type2: str) -> str: - return f""" - {stencil_func_prefix}void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{ - result_int_{type2}(floor_div((float)arg1, (float)arg2), arg2); - }} - """ + if type1 == 'int' and type2 == 'int': + return f""" + {stencil_func_prefix}void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + result_int_{type2}(floor_div((float)arg1, (float)arg2), arg2); + }} + """ + else: + return f""" + {stencil_func_prefix}void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{ + result_float_{type2}((float)floor_div((float)arg1, (float)arg2), arg2); + }} + """ def get_result_stubs1(type1: str) -> str: