patching of subfunction fixed and types for // aligned to python standard

This commit is contained in:
Nicolas 2025-10-14 22:59:51 +02:00
parent 1ea7ee9fdb
commit b5e6130eb8
6 changed files with 33 additions and 29 deletions

View File

@ -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: 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])}") 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' result_type = 'bool'
else: else:
result_type = generic_sdb.stencil_definitions[typed_op].split('_')[0] 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 # Prepare program code and relocations
object_addr_lookup = {net: offs for net, offs, _ in variable_mem_layout} object_addr_lookup = {net: offs for net, offs, _ in variable_mem_layout}
data_list: list[bytes] = [] 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 offset = aux_function_lengths # offset in generated code chunk
# assemble stencils to main program # assemble stencils to main program
@ -429,14 +429,15 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database
if patch.target_symbol_info == 'STT_OBJECT': if patch.target_symbol_info == 'STT_OBJECT':
assert associated_net, f"Relocation found but no net defined for operation {node.name}" assert associated_net, f"Relocation found but no net defined for operation {node.name}"
addr = object_addr_lookup[associated_net] 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': elif patch.target_symbol_info == 'STT_FUNC':
addr = aux_func_addr_lookup[patch.target_symbol_name] 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: else:
raise ValueError(f"Unsupported: {node.name} {patch.target_symbol_info} {patch.target_symbol_name}") 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) offset += len(data)
data = sdb.get_function_code('entry_function_shell', 'end') data = sdb.get_function_code('entry_function_shell', 'end')
@ -462,8 +463,8 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database
dw.write_bytes(b''.join(data_list)) dw.write_bytes(b''.join(data_list))
# write relocations # write relocations
for patch_type, patch_addr, addr in patch_list: for patch_type, patch_addr, addr, patch_command in patch_list:
dw.write_com(binw.Command.PATCH_OBJECT) dw.write_com(patch_command)
dw.write_int(patch_addr) dw.write_int(patch_addr)
dw.write_int(patch_type) dw.write_int(patch_type)
dw.write_int(addr, signed=True) dw.write_int(addr, signed=True)

View File

@ -113,7 +113,7 @@ int parse_commands(uint8_t *bytes) {
break; break;
case RUN_PROG: case RUN_PROG:
printf("RUN_PROG"); printf("RUN_PROG\n");
int ret = entr_point(); int ret = entr_point();
printf("Return value: %i\n", ret); printf("Return value: %i\n", ret);
break; break;

View File

@ -6,10 +6,10 @@ from copapy import binwrite
def run_command(command: list[str], encoding: str = 'utf8') -> str: 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() 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) return output.decode(encoding)
@ -35,7 +35,7 @@ def test_example():
def function(c1, c2): def function(c1, c2):
i1 = c1 * 3.3 + 5 i1 = c1 // 3.3 + 5
i2 = c2 * 5 + c1 i2 = c2 * 5 + c1
#r1 = i1 + i2 * 55 / 4 #r1 = i1 + i2 * 55 / 4
r1 = i1 + i2 * 55 / 4 r1 = i1 + i2 * 55 / 4
@ -57,7 +57,6 @@ def test_compile():
# run program command # run program command
il.write_com(binwrite.Command.RUN_PROG) il.write_com(binwrite.Command.RUN_PROG)
il.write_int(0)
il.write_com(binwrite.Command.READ_DATA) il.write_com(binwrite.Command.READ_DATA)
il.write_int(0) il.write_int(0)
@ -71,8 +70,9 @@ def test_compile():
il.to_file('bin/test.copapy') il.to_file('bin/test.copapy')
result = run_command(['bin/coparun', 'bin/test.copapy']) result = run_command(['bin/coparun', 'bin/test.copapy'])
print('* Output from runner:') print('* Output from runner:\n--')
print(result) print(result)
print('--')
assert 'Return value: 1' in result assert 'Return value: 1' in result

View File

@ -25,29 +25,25 @@ def function5(c1):
def test_compile(): def test_compile():
c1 = CPVariable(9) c_i = CPVariable(9)
c2 = CPVariable(1.111) c_f = CPVariable(1.111)
c3 = CPVariable(False) c_b = CPVariable(True)
#ret_test = function1(c1) + function1(c2) + function2(c1) + function2(c2) + function3(c3) + function4(c1) + function5(c3) + [CPVariable(9) % 2] 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] 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]
print(ret_test) print(ret_test)
tg = Target() tg = Target()
print('* compile and copy ...') print('* compile and copy ...')
tg.compile(ret_test) tg.compile(ret_test)
#time.sleep(5)
print('* run and copy ...') print('* run and copy ...')
tg.run() tg.run()
print('* finished') print('* finished')
for test, ref in zip(ret_test, ret_ref): for test, ref in zip(ret_test, ret_ref):
val = tg.read_value(test) val = tg.read_value(test)
print('+', val, ref) #print('+', val, ref, test.dtype)
for t in [int, float, bool]: for t in [int, float, bool]:
assert isinstance(val, t) == isinstance(ref, t), f"Result type does not match for {val} and {ref}" 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}" assert val == approx(ref, 1e-5), f"Result does not match: {val} and reference: {ref}"

View File

@ -6,7 +6,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("input_file", type=str, help="Input file path with copapy commands") 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("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") parser.add_argument("--byteorder", type=str, choices=['little', 'big'], default='little', help="Select byteorder")
args = parser.parse_args() args = parser.parse_args()

View File

@ -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: def get_floordiv(op: str, type1: str, type2: str) -> str:
return f""" if type1 == 'int' and type2 == 'int':
{stencil_func_prefix}void {op}_{type1}_{type2}({type1} arg1, {type2} arg2) {{ return f"""
result_int_{type2}(floor_div((float)arg1, (float)arg2), arg2); {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: def get_result_stubs1(type1: str) -> str: