csullivan commented on a change in pull request #9631: URL: https://github.com/apache/tvm/pull/9631#discussion_r764466650
########## File path: python/tvm/contrib/hexagon/build.py ########## @@ -0,0 +1,259 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +"""Defines top-level glue functions for building Hexagon.""" + +import pathlib +import os +import subprocess +from typing import Union +import stat +import datetime + +import tvm +from ..._ffi import libinfo +from .session import Session + + +RPC_SERVER_FILES = ["tvm_rpc_android", "libtvm_runtime_android.so", "android_bash.sh"] + +HEXAGON_FILES = ["libhexagon_rpc_skel.so"] + +HEXAGON_RPC_DIR = None + +ANDROID_HEXAGON_TEST_BASE_DIR = pathlib.Path("/data/local/tmp/hexagon_test") + + +def get_hexagon_rpc_dir() -> pathlib.Path: + """Find the Hexagon library. + + Returns + ------- + str : + The path to the Hexagon library + """ + global HEXAGON_RPC_DIR + if HEXAGON_RPC_DIR is None: + for path in libinfo.find_lib_path(): + rpc_dir = os.path.join(os.path.dirname(path), "hexagon_rpc") + if os.path.isdir(rpc_dir): + HEXAGON_RPC_DIR = pathlib.Path(rpc_dir) + break + else: + raise "hexagon_rpc was not found." + return HEXAGON_RPC_DIR + + +class HexagonLauncher: + """Hexagon Launcher""" + + def __init__(self, serial_number: str): + """Configure a new HexagonLauncher + + Parameters + ---------- + serial_number : str + Android device serial number from android 'adb' command. + """ + # Hexagon RPCSession + self.session = None + + self._serial_number = serial_number + self._adb_device_sub_cmd = ["adb", "-s", self._serial_number] + self._mod = None + self._workspace = None + + HEXAGON_REMOTE_DEVICE_KEY = "hexagon-dev" + + def android_run_rpc( + self, + workspace_dir: Union[str, pathlib.Path] = None, + rpc_server_port: int = 7070, + rpc_tracker_host: str = "0.0.0.0", + rpc_tracker_port: int = 9190, + ): + """Upload Android artifacts and run RPC server on Android. + + Parameters + ---------- + workspace_dir : Union[str, pathlib.Path] + Workspace directory used on Android to upload artifacts. + + rpc_server_port : int + Android RPC server port number + + rpc_tracker_host : str + RPC tracker IP on host + + rpc_tracker_port : int + RPC tracker port on host + """ + if not workspace_dir: + self._workspace = str( + ANDROID_HEXAGON_TEST_BASE_DIR + / datetime.datetime.now().strftime("%Y-%m-%dT%H-%M-%S") + ) + else: + self._workspace = workspace_dir + + # Upload RPC server and libraries + subprocess.check_call(self._adb_device_sub_cmd + ["shell", "mkdir", "-p", self._workspace]) + + # create bash script + android_bash_script_path = get_hexagon_rpc_dir() / "android_bash.sh" + with open(get_hexagon_rpc_dir() / "android_bash.sh.template", "r") as src_f: + if os.path.exists(android_bash_script_path): + os.remove(android_bash_script_path) + with open(android_bash_script_path, "w") as dest_f: + for line in src_f.readlines(): + if "<RPC_TRACKER_HOST>" in line: + line = line.replace("<RPC_TRACKER_HOST>", str(rpc_tracker_host)) + if "<RPC_TRACKER_PORT>" in line: + line = line.replace("<RPC_TRACKER_PORT>", str(rpc_tracker_port)) + if "<HEXAGON_REMOTE_DEVICE_KEY>" in line: + line = line.replace( + "<HEXAGON_REMOTE_DEVICE_KEY>", self.HEXAGON_REMOTE_DEVICE_KEY + ) + if "<RPC_SERVER_PORT>" in line: + line = line.replace("<RPC_SERVER_PORT>", str(rpc_server_port)) + dest_f.write(line) + + # make shell script executable + android_bash_stat = os.stat(android_bash_script_path) + os.chmod(android_bash_script_path, android_bash_stat.st_mode | stat.S_IEXEC) + + # push files + for item in RPC_SERVER_FILES: + src_path = get_hexagon_rpc_dir() / item + destination = f"{self._workspace}/{item}" + if item == "libtvm_runtime_android.so": + destination = f"{self._workspace}/libtvm_runtime.so" + subprocess.check_call(self._adb_device_sub_cmd + ["push", src_path, destination]) + + # enable root for adb + subprocess.check_call(self._adb_device_sub_cmd + ["root"]) + # Removed pre-defined forward/reverse rules + subprocess.check_call(self._adb_device_sub_cmd + ["forward", "--remove-all"]) + subprocess.check_call(self._adb_device_sub_cmd + ["reverse", "--remove-all"]) + + # Enable port reverse for RPC tracker + subprocess.check_call( + self._adb_device_sub_cmd + + ["reverse", f"tcp:{rpc_tracker_port}", f"tcp:{rpc_tracker_port}"] + ) + # Enable port forward for RPC server. We forward 9 ports after the rpc_server_port. + for i in range(0, 10): + subprocess.check_call( + self._adb_device_sub_cmd + + ["forward", f"tcp:{rpc_server_port+i}", f"tcp:{rpc_server_port+i}"] Review comment: In my experiments I've not needed to setup up port forwarding and reversing for the RPC server to connect to the tracker. I was able to remove these in your code and run the tests okay. That may be because the adb session already had these forwarded and reversed. That's perhaps another reason why I don't like making port forward/reversing changes as they change the state of the adb session even after the tests complete. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
