diff --git a/src/copapy/__init__.py b/src/copapy/__init__.py index a30c9df..db79e08 100644 --- a/src/copapy/__init__.py +++ b/src/copapy/__init__.py @@ -334,19 +334,19 @@ def get_nets(*inputs: Iterable[Iterable[Any]]) -> list[Net]: return list(nets) -def get_variable_mem_layout(variable_list: list[Net], sdb: stencil_database) -> tuple[list[tuple[Net, int, int]], int]: +def get_variable_mem_layout(variable_list: Iterable[Net], sdb: stencil_database) -> tuple[list[tuple[Net, int, int]], int]: offset: int = 0 object_list: list[tuple[Net, int, int]] = [] for variable in variable_list: - lengths = sdb.var_size['dummy_' + variable.dtype] + lengths = sdb.get_symbol_size('dummy_' + variable.dtype) object_list.append((variable, offset, lengths)) offset += (lengths + 3) // 4 * 4 return object_list, offset -def get_aux_function_mem_layout(function_names: list[str], sdb: stencil_database) -> tuple[list[tuple[str, int, int]], int]: +def get_aux_function_mem_layout(function_names: Iterable[str], sdb: stencil_database) -> tuple[list[tuple[str, int, int]], int]: offset: int = 0 function_list: list[tuple[str, int, int]] = [] @@ -375,11 +375,11 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database variable_list = get_nets([[const_net_list]], extended_output_ops) # Write data - object_list, data_section_lengths = get_variable_mem_layout(variable_list, sdb) + variable_mem_layout, data_section_lengths = get_variable_mem_layout(variable_list, sdb) dw.write_com(binw.Command.ALLOCATE_DATA) dw.write_int(data_section_lengths) - for net, out_offs, lengths in object_list: + for net, out_offs, lengths in variable_mem_layout: variables[net] = (out_offs, lengths, net.dtype) if isinstance(net.source, InitVar): dw.write_com(binw.Command.COPY_DATA) @@ -388,25 +388,22 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database dw.write_value(net.source.value, lengths) # print(f'+ {net.dtype} {net.source.value}') - # Write auxiliary_functions - object_list, data_section_lengths = get_aux_function_mem_layout(variable_list, sdb) - dw.write_com(binw.Command.ALLOCATE_DATA) - dw.write_int(data_section_lengths) + # write auxiliary_functions + aux_function_names = sdb.get_sub_functions(node.name for _, node in extended_output_ops) + aux_function_mem_layout, aux_function_lengths = get_aux_function_mem_layout(aux_function_names, sdb) + aux_func_addr_lookup = {name: offs for name, offs, _ in aux_function_mem_layout} - for net, out_offs, lengths in object_list: - variables[net] = (out_offs, lengths, net.dtype) - if isinstance(net.source, InitVar): - dw.write_com(binw.Command.COPY_DATA) - dw.write_int(out_offs) - dw.write_int(lengths) - dw.write_value(net.source.value, lengths) - # print(f'+ {net.dtype} {net.source.value}') + dw.write_com(binw.Command.COPY_CODE) + dw.write_int(0) + dw.write_int(aux_function_lengths) + for name, _, _ in aux_function_mem_layout: + dw.write_bytes(sdb.get_function_code(name)) # Prepare program code and relocations - object_addr_lookup = {net: out_offs for net, out_offs, _ in object_list} + object_addr_lookup = {net: offs for net, offs, _ in variable_mem_layout} data_list: list[bytes] = [] patch_list: list[tuple[int, int, int]] = [] - offset = 0 # offset in generated code chunk + offset = aux_function_lengths # offset in generated code chunk # assemble stencils to main program data = sdb.get_function_code('entry_function_shell', 'start') @@ -422,13 +419,15 @@ def compile_to_instruction_list(node_list: Iterable[Node], sdb: stencil_database for patch in sdb.get_patch_positions(node.name): if patch.target_symbol_info == 'STT_OBJECT': assert associated_net, f"Relocation found but no net defined for operation {node.name}" - object_addr = object_addr_lookup[associated_net] - patch_value = object_addr + patch.addend - (offset + patch.addr) - # print('patch: ', patch, object_addr, patch_value) - patch_list.append((patch.type.value, offset + patch.addr, patch_value)) - print('++ ', patch.target_symbol_info, patch.target_symbol_name) + addr = object_addr_lookup[associated_net] + elif patch.target_symbol_info == 'STT_FUNC': + addr = aux_func_addr_lookup[patch.target_symbol_name] 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)) + print('++ ', patch.target_symbol_info, patch.target_symbol_name) offset += len(data) @@ -448,11 +447,14 @@ 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, object_addr in patch_list: + for patch_type, patch_addr, addr in patch_list: dw.write_com(binw.Command.PATCH_OBJECT) dw.write_int(patch_addr) dw.write_int(patch_type) - dw.write_int(object_addr, signed=True) + dw.write_int(addr, signed=True) + + dw.write_com(binw.Command.ENTRY_POINT) + dw.write_int(aux_function_lengths) return dw, variables @@ -474,15 +476,14 @@ class Target(): nodes.append(Write(net)) dw, self._variables = compile_to_instruction_list(nodes, self.sdb) - dw.write_com(binw.Command.END_PROG) + dw.write_com(binw.Command.END_COM) assert coparun(dw.get_data()) > 0 def run(self) -> None: # set entry point and run code dw = binw.data_writer(self.sdb.byteorder) dw.write_com(binw.Command.RUN_PROG) - dw.write_int(0) - dw.write_com(binw.Command.END_PROG) + dw.write_com(binw.Command.END_COM) assert coparun(dw.get_data()) > 0 def read_value(self, net: Net) -> float | int: diff --git a/src/copapy/binwrite.py b/src/copapy/binwrite.py index 77b87ba..627b3ae 100644 --- a/src/copapy/binwrite.py +++ b/src/copapy/binwrite.py @@ -6,9 +6,9 @@ ByteOrder = Literal['little', 'big'] Command = Enum('Command', [('ALLOCATE_DATA', 1), ('COPY_DATA', 2), ('ALLOCATE_CODE', 3), ('COPY_CODE', 4), - ('PATCH_FUNC', 5), ('PATCH_OBJECT', 6), + ('PATCH_FUNC', 5), ('PATCH_OBJECT', 6), ('ENTRY_POINT', 7), ('RUN_PROG', 64), ('READ_DATA', 65), - ('END_PROG', 256), ('FREE_MEMORY', 257)]) + ('END_COM', 256), ('FREE_MEMORY', 257)]) COMMAND_SIZE = 4 diff --git a/src/copapy/stencil_db.py b/src/copapy/stencil_db.py index c06a5f4..46c3abd 100644 --- a/src/copapy/stencil_db.py +++ b/src/copapy/stencil_db.py @@ -95,9 +95,9 @@ class stencil_database(): # for s in self.elf.symbols # if s.info == 'STT_FUNC'} - self.var_size = {s.name: s.fields['st_size'] - for s in self.elf.symbols - if s.info == 'STT_OBJECT'} + #self.var_size = {s.name: s.fields['st_size'] + # for s in self.elf.symbols + # if s.info == 'STT_OBJECT'} self.byteorder: ByteOrder = self.elf.byteorder #for name in self.function_definitions.keys(): @@ -150,9 +150,10 @@ class stencil_database(): for name in names: if name not in name_set: func = self.elf.symbols[name] - for reloc in func.relocations: - name_set.add(reloc.symbol.name) - name_set |= self.get_sub_functions(name_set) + for r in func.relocations: + if r.symbol.info == 'STT_FUNC': + name_set.add(r.symbol.name) + name_set |= self.get_sub_functions([r.symbol.name]) return name_set def get_symbol_size(self, name: str) -> int: diff --git a/src/coparun/runmem.c b/src/coparun/runmem.c index 29251b0..3257678 100644 --- a/src/coparun/runmem.c +++ b/src/coparun/runmem.c @@ -104,13 +104,16 @@ int parse_commands(uint8_t *bytes) { offs, reloc_type, value); patch(executable_memory + offs, reloc_type, value + data_offs); break; + + case ENTRY_POINT: + printf("ENTRY_POINT rel_entr_point=%i\n", rel_entr_point); + rel_entr_point = *(uint32_t*)bytes; bytes += 4; + entr_point = (entry_point_t)(executable_memory + rel_entr_point); + mark_mem_executable(executable_memory, executable_memory_len); + break; case RUN_PROG: - rel_entr_point = *(uint32_t*)bytes; bytes += 4; - printf("RUN_PROG rel_entr_point=%i\n", rel_entr_point); - entr_point = (entry_point_t)(executable_memory + rel_entr_point); - - mark_mem_executable(executable_memory, executable_memory_len); + printf("RUN_PROG"); int ret = entr_point(); printf("Return value: %i\n", ret); break; diff --git a/src/coparun/runmem.h b/src/coparun/runmem.h index 6d34191..af9b61c 100644 --- a/src/coparun/runmem.h +++ b/src/coparun/runmem.h @@ -10,9 +10,10 @@ #define COPY_CODE 4 #define PATCH_FUNC 5 #define PATCH_OBJECT 6 +#define ENTRY_POINT 7 #define RUN_PROG 64 #define READ_DATA 65 -#define END_PROG 256 +#define END_COM 256 #define FREE_MEMORY 257 /* Relocation types */ diff --git a/tests/test_compile.py b/tests/test_compile.py index f020231..2b5f4dc 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -63,7 +63,7 @@ def test_compile(): il.write_int(0) il.write_int(36) - il.write_com(binwrite.Command.END_PROG) + il.write_com(binwrite.Command.END_COM) print('* Data to runner:') il.print() diff --git a/tests/test_compile_div.py b/tests/test_compile_div.py index c890a6f..d9e501c 100644 --- a/tests/test_compile_div.py +++ b/tests/test_compile_div.py @@ -29,13 +29,12 @@ 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) il.write_int(36) - il.write_com(binwrite.Command.END_PROG) + il.write_com(binwrite.Command.END_COM) print('* Data to runner:') il.print() diff --git a/tests/test_coparun_module2.py b/tests/test_coparun_module2.py index e0a2d0f..19bd9fe 100644 --- a/tests/test_coparun_module2.py +++ b/tests/test_coparun_module2.py @@ -25,7 +25,7 @@ def test_compile(): il.write_int(36) # run program command - il.write_com(binwrite.Command.END_PROG) + il.write_com(binwrite.Command.END_COM) #print('* Data to runner:') #il.print() diff --git a/tests/test_crash_win.py b/tests/test_crash_win.py index 35fa7ff..461894f 100644 --- a/tests/test_crash_win.py +++ b/tests/test_crash_win.py @@ -42,7 +42,7 @@ def test_compile(): print('+', name) copapy.add_read_command(dw, variable_list, net) - dw.write_com(binwrite.Command.END_PROG) + dw.write_com(binwrite.Command.END_COM) dw.to_file('bin/test.copapy') result = run_command(['bin/coparun', 'bin/test.copapy']) diff --git a/tools/extract_code.py b/tools/extract_code.py index becaf8a..c55db07 100644 --- a/tools/extract_code.py +++ b/tools/extract_code.py @@ -55,17 +55,20 @@ if __name__ == "__main__": assert reloc_type == RelocationType.RELOC_RELATIVE_32.value program_data[offs:offs + 4] = (value + data_section_offset).to_bytes(4, byteorder, signed=True) print(f"PATCH_OBJECT patch_offs={offs} reloc_type={reloc_type} value={value}") + elif com == Command.ENTRY_POINT: + rel_entr_point = dr.read_int() + print(f"ENTRY_POINT rel_entr_point={rel_entr_point}") elif com == Command.RUN_PROG: rel_entr_point = dr.read_int() - print(f"RUN_PROG rel_entr_point={rel_entr_point}") + print(f"RUN_PROG") elif com == Command.READ_DATA: offs = dr.read_int() size = dr.read_int() print(f"READ_DATA offs={offs} size={size}") elif com == Command.FREE_MEMORY: print("READ_DATA") - elif com == Command.END_PROG: - print("END_PROG") + elif com == Command.END_COM: + print("END_COM") end_flag = 1 else: assert False, f"Unknown command: {com}" diff --git a/tools/make_example.py b/tools/make_example.py index 8257d90..3c70f17 100644 --- a/tools/make_example.py +++ b/tools/make_example.py @@ -16,13 +16,12 @@ def test_compile() -> None: # 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) il.write_int(36) - il.write_com(binwrite.Command.END_PROG) + il.write_com(binwrite.Command.END_COM) print('* Data to runner:') il.print()