From 49d8d9577337f60f4901da813a8126af16b907f9 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 28 Apr 2026 11:40:02 +0200 Subject: [PATCH] helper scripts added for running tricore code in qemu. Not working yet. Co-authored-by: Copilot --- tools/build.bat | 2 +- tools/tricore/make_trc_example.py | 15 ++++ tools/tricore/run_qemu.py | 113 ++++++++++++++++++++++++++++++ tools/tricore/run_test.bat | 3 + 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 tools/tricore/make_trc_example.py create mode 100644 tools/tricore/run_qemu.py create mode 100644 tools/tricore/run_test.bat diff --git a/tools/build.bat b/tools/build.bat index f501ca6..2175980 100644 --- a/tools/build.bat +++ b/tools/build.bat @@ -36,7 +36,7 @@ echo - Compile stencil test... cl /Zi /Od stencils\test.c /Fe:build\stencils\test.exe echo - Build runner for Windows 64 bit... -cl /Zi /Od /DENABLE_BASIC_LOGGING ^ +cl /Zi /Od /DENABLE_LOGGING ^ src\coparun\runmem.c ^ src\coparun\coparun.c ^ src\coparun\mem_man.c ^ diff --git a/tools/tricore/make_trc_example.py b/tools/tricore/make_trc_example.py new file mode 100644 index 0000000..c3466a9 --- /dev/null +++ b/tools/tricore/make_trc_example.py @@ -0,0 +1,15 @@ +from copapy import value +from copapy.backend import Store, compile_to_dag, stencil_db_from_package +from copapy._binwrite import Command + +input = value(9.0) + +result = input ** 2 / 3.3 + 5 + +sdb = stencil_db_from_package('tricore') +dw, _ = compile_to_dag([Store(result)], sdb) + +# Instruct runner to dump patched code to a file: +dw.write_com(Command.DUMP_CODE) + +dw.to_file('build/runner/test-tricore.copapy') diff --git a/tools/tricore/run_qemu.py b/tools/tricore/run_qemu.py new file mode 100644 index 0000000..8d26586 --- /dev/null +++ b/tools/tricore/run_qemu.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +""" +Load two raw blobs into qemu-system-tricore memory and execute them +""" + +import argparse +import subprocess +import sys +import shutil +import os +import tempfile +from pathlib import Path + +if os.name == 'nt': + QEMU_BIN = ['wsl', '/opt/tricore/bin/qemu-system-tricore'] +else: + QEMU_BIN = ['qemu-system-tricore'] + +MACHINE = "tc27x" +RESET_VECTOR = 0x80000000 + +def check_qemu(): + if os.name == 'nt': + # On Windows, just check if wsl is available + if shutil.which('wsl') is None: + print("Cannot find 'wsl' in PATH") + sys.exit(1) + else: + if shutil.which(QEMU_BIN[0]) is None: + print(f"Cannot find {QEMU_BIN[0]} in PATH") + sys.exit(1) + +def make_jump_trampoline(entry_addr: int, out_file: Path): + """ + Generate a TriCore jump instruction to entry_addr from RESET_VECTOR. + Uses a 24-bit relative jump instruction: j offset + + Instruction encoding: + - Byte 0: 0x1d (opcode for relative jump) + - Bytes 1-3: 24-bit signed relative offset + + Raises an error if the offset doesn't fit in 24 bits. + """ + # Calculate relative offset from RESET_VECTOR to entry_addr + # offset = entry_addr - (RESET_VECTOR + instruction_size) + offset = entry_addr - (RESET_VECTOR + 4) + + # Check if offset fits in 24-bit signed range: [-2^23, 2^23-1] + max_24bit = (1 << 23) - 1 + min_24bit = -(1 << 23) + + if offset < min_24bit or offset > max_24bit: + raise ValueError( + f"24-bit relative jump is not sufficient. " + f"Offset {offset} (0x{offset:x}) is outside [-2^23, 2^23-1] range. " + f"RESET_VECTOR: 0x{RESET_VECTOR:x}, entry_addr: 0x{entry_addr:x}" + ) + + # Encode the 24-bit offset in little-endian format (3 bytes) + offset_bytes = offset.to_bytes(3, byteorder='little', signed=True) + + # Create the jump instruction: opcode (0x1d) + 24-bit offset + instruction = bytes([0x1d]) + offset_bytes + + out_file.write_bytes(instruction) + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--code", required=True, help="code blob") + ap.add_argument("--data", required=True, help="data blob") + ap.add_argument("--code-addr", required=True, type=lambda x:int(x,0)) + ap.add_argument("--data-addr", required=True, type=lambda x:int(x,0)) + ap.add_argument("--entry", required=True, type=lambda x:int(x,0)) + ap.add_argument("--machine", default=MACHINE) + args = ap.parse_args() + + check_qemu() + + # Create temporary file for trampoline + with tempfile.NamedTemporaryFile(delete=False, suffix='.bin') as tmp: + tramp = Path(tmp.name) + + try: + make_jump_trampoline(args.entry, tramp) + + cmd = list(QEMU_BIN) + [ + "-M", args.machine, + "-nographic", + + # reset vector trampoline + "-device", f"loader,file={tramp},addr=0x{RESET_VECTOR:x}", + + # user code/data + "-device", f"loader,file={args.code},addr=0x{args.code_addr:x}", + "-device", f"loader,file={args.data},addr=0x{args.data_addr:x}", + + # logs + "-d", "in_asm,exec,cpu,guest_errors", + "-D", "qemu.log", + ] + + print("Running:") + print(" ".join(cmd)) + print() + + subprocess.run(cmd) + finally: + # Clean up temporary file + if tramp.exists(): + tramp.unlink() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/tricore/run_test.bat b/tools/tricore/run_test.bat new file mode 100644 index 0000000..00845c4 --- /dev/null +++ b/tools/tricore/run_test.bat @@ -0,0 +1,3 @@ +python tools\tricore\make_trc_example.py +build\runner\coparun build/runner/test-tricore.copapy build/runner/test-tricore.copapy.bin +python .\tools\tricore\run_qemu.py --code build/runner/test-tricore.copapy.bin \ No newline at end of file