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:
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,14 +429,15 @@ 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)
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))
# 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)

View File

@ -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;

View File

@ -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

View File

@ -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}"

View File

@ -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()

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:
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: