diff --git a/.github/workflows/local-benchmarks.yml b/.github/workflows/local-benchmarks.yml new file mode 100644 index 0000000..4744206 --- /dev/null +++ b/.github/workflows/local-benchmarks.yml @@ -0,0 +1,79 @@ +name: Local Benchmarks CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + local-benchmark-test: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repository with submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up Java 17 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '17' + + - name: Set up Python 3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Python dependencies + run: | + pip install paramiko pandas seaborn imageio matplotlib + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake ninja-build + + - name: Build Lingua Franca compiler + run: | + cd lingua-franca + ./gradlew assemble + + - name: Build and install trace utilities + run: | + cd lingua-franca/core/src/main/resources/lib/c/reactor-c/util/tracing + make trace_to_csv trace_to_chrome + sudo cp trace_to_csv trace_to_chrome /usr/local/bin/ + + - name: Add lfc to PATH + run: | + echo "${{ github.workspace }}/lingua-franca/bin" >> $GITHUB_PATH + + - name: Verify lfc installation + run: | + lfc-dev --version + trace_to_csv --help | head -3 + + - name: Run local benchmark test (PingPong with NP scheduler) + run: | + cd benchmarks + python3 scripts/run_benchmark.py --local --src=src --src-gen=src-gen --select=PingPong -f=--scheduler=NP + + - name: Verify benchmark output + run: | + # Check that CSV file was generated + ls -la benchmarks/data/ + CSV_DIR=$(ls -td benchmarks/data/*/ | head -1) + echo "Checking directory: $CSV_DIR" + ls -la "$CSV_DIR" + test -f "${CSV_DIR}PingPong.csv" && echo "CSV file generated successfully" + test -f "${CSV_DIR}PingPong.lft" && echo "LFT trace file generated successfully" + + - name: Upload benchmark artifacts + uses: actions/upload-artifact@v4 + with: + name: benchmark-results + path: benchmarks/data/ + retention-days: 7 diff --git a/.gitignore b/.gitignore index ecabc16..90cf8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,7 @@ benchmarks/experiment-data benchmarks/scripts/credentials.py +benchmarks/data +benchmarks/include .vscode/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ee6d877 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,83 @@ +FROM ubuntu:22.04 + +# Timezone and locale +ENV TZ="UTC" +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Base packages +RUN apt-get update && apt-get install -y \ + git wget curl tar sudo apt-utils software-properties-common \ + && rm -rf /var/lib/apt/lists/* + +# Build tools +RUN apt-get update && apt-get install -y \ + build-essential ninja-build cmake make pkg-config libssl-dev \ + && rm -rf /var/lib/apt/lists/* + +# Java 17 (for Lingua Franca compiler) +RUN apt-get update && apt-get install -y openjdk-17-jdk \ + && rm -rf /var/lib/apt/lists/* +ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 + +# Python 3 +RUN apt-get update && apt-get install -y python3 python3-pip python3-venv \ + && rm -rf /var/lib/apt/lists/* + +# Python dependencies for benchmarks +RUN pip3 install --no-cache-dir \ + paramiko==3.5.0 pandas==2.2.3 seaborn==0.13.2 imageio==2.36.0 matplotlib + +# Python dependencies for EGS +RUN pip3 install --no-cache-dir \ + numpy==2.1.3 scipy==1.15.2 tensorflow==2.19.0 + +# Ruby (for WCET analysis tools) +RUN apt-get update && apt-get install -y ruby ruby-dev \ + && rm -rf /var/lib/apt/lists/* +RUN gem install bundler -v 2.4.22 + +# Verilator (for FlexPRET emulator) +RUN apt-get update && apt-get install -y verilator \ + && rm -rf /var/lib/apt/lists/* + +# Scala/SBT (for FlexPRET build) +RUN apt-get update && apt-get install -y gnupg2 \ + && rm -rf /var/lib/apt/lists/* +RUN echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | tee /etc/apt/sources.list.d/sbt.list +RUN echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | tee /etc/apt/sources.list.d/sbt_old.list +RUN curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | apt-key add +RUN apt-get update && apt-get install -y scala sbt \ + && rm -rf /var/lib/apt/lists/* + +# RISC-V Toolchain (xPack) +ENV RISCV_VERSION=14.2.0-2 +RUN mkdir -p /opt && cd /opt \ + && wget -q https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v${RISCV_VERSION}/xpack-riscv-none-elf-gcc-${RISCV_VERSION}-linux-x64.tar.gz \ + && tar -xzf xpack-riscv-none-elf-gcc-${RISCV_VERSION}-linux-x64.tar.gz \ + && rm xpack-riscv-none-elf-gcc-${RISCV_VERSION}-linux-x64.tar.gz +ENV RISCV_TOOL_PATH_PREFIX=/opt/xpack-riscv-none-elf-gcc-${RISCV_VERSION} +ENV PATH="${RISCV_TOOL_PATH_PREFIX}/bin:${PATH}" + +# WCET analysis dependencies (from case-study) +RUN apt-get update && apt-get install -y \ + liblpsolve55-dev lp-solve \ + libc6-dev-i386 gcc-multilib \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /workspace + +# Setup environment script +RUN echo '#!/bin/bash\n\ +export RISCV_TOOL_PATH_PREFIX=/opt/xpack-riscv-none-elf-gcc-14.2.0-2\n\ +export PATH="${RISCV_TOOL_PATH_PREFIX}/bin:${PATH}"\n\ +if [ -d "/workspace/lingua-franca/build/install/lf-cli/bin" ]; then\n\ + export PATH="/workspace/lingua-franca/build/install/lf-cli/bin:${PATH}"\n\ + export LFC=/workspace/lingua-franca/build/install/lf-cli/bin/lfc\n\ +fi\n\ +if [ -f "/workspace/flexpret/env.bash" ]; then\n\ + source /workspace/flexpret/env.bash\n\ +fi' > /setup_env.sh && chmod +x /setup_env.sh + +RUN echo 'source /setup_env.sh' >> /root/.bashrc + +ENTRYPOINT ["/bin/bash"] diff --git a/benchmarks/scripts/experiment_timing.py b/benchmarks/scripts/experiment_timing.py index 62b7415..b499335 100644 --- a/benchmarks/scripts/experiment_timing.py +++ b/benchmarks/scripts/experiment_timing.py @@ -13,8 +13,8 @@ import imageio # NOTE: Ensure that there is a credentials.py that defines the IP, username, and -# password of the target platform. -import credentials +# password of the target platform (only needed for remote mode). +# import credentials # Imported conditionally in main() when not in local mode ################## CONFIGS ################## @@ -69,6 +69,19 @@ default="qnx/low_level_platform", help="Specify the directory containing QNX support files." ) +parser.add_argument( + "-l", + "--local", + action="store_true", + help="Run benchmarks locally instead of on a remote embedded device." +) +parser.add_argument( + "-s", + "--select", + type=str, + action='append', + help="Select a list of programs to run instead of the entire directory (--select can be specified multiple times). No .lf extension is needed.", +) def set_ssh_info(): @@ -558,7 +571,14 @@ def main(args=None): # Parse arguments. args = parser.parse_args(args) platform = args.platform - IP, PW, UN = set_ssh_info() + + # Conditionally import credentials and set SSH info (only for remote mode) + if not args.local and args.experiment_dir is None: + import credentials + globals()['credentials'] = credentials + IP, UN, PW = set_ssh_info() + else: + IP, UN, PW = None, None, None # Variable declarations expr_data_dirname = "experiment-data/" @@ -579,10 +599,11 @@ def main(args=None): timing_dir.mkdir(exist_ok=True) # Create a directory for this experiment run. - # Time at which the script starts + # Time at which the script starts (command line --select takes priority over config) + programs_to_select = args.select if args.select else SELECT_PROGRAMS if args.experiment_dir is None: time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") # Format: Year-Month-Day_Hour-Minute-Second - expr_run_dir = timing_dir / (time + "-" + platform + "-" + "_".join(STATIC_SCHEDULER_NAMES) + "-" + ("_".join(SELECT_PROGRAMS) if len(SELECT_PROGRAMS) > 0 else "ALL")) + expr_run_dir = timing_dir / (time + "-" + platform + "-" + "_".join(STATIC_SCHEDULER_NAMES) + "-" + ("_".join(programs_to_select) if len(programs_to_select) > 0 else "ALL")) expr_run_dir.mkdir() else: expr_run_dir = timing_dir / args.experiment_dir @@ -601,26 +622,34 @@ def main(args=None): if args.experiment_dir is None: # Prepare arguments for each run_benchmark call. - args_1 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=NP", "-dd="+str(np_dir.resolve()), "--src=src", "--src-gen=src-gen"] - args_2 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=LB", "-dd="+str(lb_dir.resolve()), "--src=src", "--src-gen=src-gen"] - args_3 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=EGS", "-dd="+str(egs_dir.resolve()), "--src=src", "--src-gen=src-gen"] - if platform == "RPI4-QNX": - qnx_support_directory = Path(args.qnx_support_directory).resolve() - args_1.append("-qd=" + str(qnx_support_directory)) - args_2.append("-qd=" + str(qnx_support_directory)) - args_3.append("-qd=" + str(qnx_support_directory)) - + if args.local: + # LOCAL MODE: Use -l flag instead of SSH credentials + args_1 = ["-l", "-pl=" + platform, "-f=--scheduler=NP", "-dd="+str(np_dir.resolve()), "--src=src", "--src-gen=src-gen"] + args_2 = ["-l", "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=LB", "-dd="+str(lb_dir.resolve()), "--src=src", "--src-gen=src-gen"] + args_3 = ["-l", "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=EGS", "-dd="+str(egs_dir.resolve()), "--src=src", "--src-gen=src-gen"] + else: + # REMOTE MODE: Use SSH credentials + args_1 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=NP", "-dd="+str(np_dir.resolve()), "--src=src", "--src-gen=src-gen"] + args_2 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=LB", "-dd="+str(lb_dir.resolve()), "--src=src", "--src-gen=src-gen"] + args_3 = ["-hn=" + IP, "-un=" + UN, "-pwd=" + PW, "-pl=" + platform, "-f=--scheduler=STATIC", "-f=--mapper=EGS", "-dd="+str(egs_dir.resolve()), "--src=src", "--src-gen=src-gen"] + if platform == "RPI4-QNX": + qnx_support_directory = Path(args.qnx_support_directory).resolve() + args_1.append("-qd=" + str(qnx_support_directory)) + args_2.append("-qd=" + str(qnx_support_directory)) + args_3.append("-qd=" + str(qnx_support_directory)) + if DASH_MODE: args_2.append("-f=--dash") args_3.append("-f=--dash") - - # Select programs - if len(SELECT_PROGRAMS) > 0: - for prog in SELECT_PROGRAMS: + + # Select programs from command line argument (takes priority over config) + programs_to_select = args.select if args.select else SELECT_PROGRAMS + if len(programs_to_select) > 0: + for prog in programs_to_select: args_1.append("--select="+prog) args_2.append("--select="+prog) args_3.append("--select="+prog) - + # Exclude programs based on scheduler. if len(EXCLUDED_PROGRAMS) > 0: for prog in EXCLUDED_PROGRAMS['NP']: @@ -629,11 +658,11 @@ def main(args=None): args_2.append("--exclude="+prog) for prog in EXCLUDED_PROGRAMS['EGS']: args_3.append("--exclude="+prog) - + # Run the benchmark runner using the NP and the STATIC scheduler. # NOTE: The 2nd run's src-gen is copied back the host. So it's better to # be static because we want to inspect the graphs. - run_benchmark.main(args_1) # NP + run_benchmark.main(args_1) # NP run_benchmark.main(args_2) # LB run_benchmark.main(args_3) # EGS @@ -646,9 +675,10 @@ def main(args=None): except Exception as e: print(f"Error occurred: {e}") - # Get a list of benchmark names - if len(SELECT_PROGRAMS) > 0: - program_names = SELECT_PROGRAMS + # Get a list of benchmark names (command line --select takes priority over config) + programs_to_select = args.select if args.select else SELECT_PROGRAMS + if len(programs_to_select) > 0: + program_names = programs_to_select else: # Extract all program names from the benchmark directory. program_names = [str(file).split("/")[-1][:-3] for file in timing_benchmark_dir.glob('*') if file.is_file()] diff --git a/benchmarks/scripts/run_benchmark.py b/benchmarks/scripts/run_benchmark.py index 5f57544..6227e84 100644 --- a/benchmarks/scripts/run_benchmark.py +++ b/benchmarks/scripts/run_benchmark.py @@ -157,6 +157,12 @@ ) parser.add_argument("-nr", "--no-run", action="store_true", help="Skip running the compiled programs.") parser.add_argument("-np", "--no-parse", action="store_true", help="Skip conversion of traces to csv") +parser.add_argument( + "-l", + "--local", + action="store_true", + help="Run benchmarks locally instead of on a remote embedded device." +) parser.add_argument( "-pl", "--platform", @@ -195,7 +201,9 @@ def host_compile_lf_file(args, filename): cmd = ["lfc-dev", "-n"] if not args.no_tracing: cmd.append("--tracing") - cmd += args.flag + [filename] + if args.flag: + cmd += args.flag + cmd.append(filename) print("Executing local command: " + " ".join(cmd)) result = host_execute_cmd(cmd) print("Exit code:", result.returncode) @@ -363,6 +371,99 @@ def host_process_trace_data(): return 1 +#################################################### +############### Local Functions ############### +#################################################### + + +def local_compile_cmake_project(dir, arg1, arg2, arg3): + """Compile CMake project locally using subprocess.""" + print("Compiling locally: " + dir) + build_dir = os.path.join(dir, "build") + os.makedirs(build_dir, exist_ok=True) + + # Run cmake + cmake_cmd = ["cmake", ".."] + result = subprocess.run(cmake_cmd, cwd=build_dir, capture_output=True, text=True) + if result.returncode != 0: + print("CMAKE STDERR:", result.stderr) + return + + # Run make + make_cmd = ["make"] + result = subprocess.run(make_cmd, cwd=build_dir, capture_output=True, text=True) + if result.returncode != 0: + print("MAKE STDERR:", result.stderr) + else: + print("Successfully compiled: " + dir) + + +def local_run_program(dir, data_dir, command_line_args, arg3=None): + """ + Execute compiled LF program locally. + Extract the binary name from the dir path. + E.g., path = /home/user/benchmarks/CoopSchedule/, + then bin = CoopSchedule. + """ + bin_name = os.path.basename(os.path.normpath(dir)) + bin_path = os.path.join(dir, "build", bin_name) + + # Change to data_dir so trace files are generated there + original_cwd = os.getcwd() + os.makedirs(data_dir, exist_ok=True) + os.chdir(data_dir) + + try: + if command_line_args.repeat == 0: + print(f"Running locally: {bin_path}") + result = subprocess.run([bin_path], capture_output=True, text=True, encoding='ISO-8859-1') + print("STDOUT:", result.stdout) + if result.stderr: + print("STDERR:", result.stderr) + else: + # Repeat the execution and write outputs in a txt file. + output_file = os.path.join(data_dir, f"{bin_name}.txt") + with open(output_file, 'w') as f: + for i in range(command_line_args.repeat): + result = subprocess.run([bin_path], capture_output=True, text=True, encoding='ISO-8859-1') + f.write(result.stdout) + + # Rename the .lft file so we know which is which. + if not command_line_args.no_tracing: + lft_source = os.path.join(data_dir, "main_0.lft") + lft_dest = os.path.join(data_dir, f"{bin_name}.lft") + if os.path.exists(lft_source): + os.rename(lft_source, lft_dest) + finally: + os.chdir(original_cwd) + + +def local_run_trace_conversion(file, dir, convert_for_chrome=False, arg3=None): + """Run trace_to_csv locally.""" + print(f"Converting trace locally: {file}") + cmd = ["trace_to_csv", file] + result = subprocess.run(cmd, cwd=dir, capture_output=True, text=True) + print("STDOUT:", result.stdout) + if result.stderr: + print("STDERR:", result.stderr) + + if convert_for_chrome: + cmd = ["trace_to_chrome", file] + result = subprocess.run(cmd, cwd=dir, capture_output=True, text=True) + print("STDOUT:", result.stdout) + if result.stderr: + print("STDERR:", result.stderr) + + +def local_forall_files_in_dir_do(func, dir, arg1=None, arg2=None, arg3=None): + """Iterate over files in a local directory and apply func to each.""" + files = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))] + print(f"Files in {dir}: {files}") + for file in files: + full_path = os.path.join(dir, file) + func(full_path, arg1, arg2, arg3) + + #################################################### ############### Remote Functions ############### #################################################### @@ -528,19 +629,26 @@ def main(args=None): # Check if the --post-only flag is set. If so, skip all prior steps and just # perform post analyses. + is_local = args.local + if not args.post_only: - # Step 2. - if not host_connect_to_remote(args): - print("Run Benchmark: Cannot connect to host! Abort.") - sys.exit(1) + if is_local: + print("Run Benchmark: Running in LOCAL mode.") + # In local mode, use host directories directly + local_data = host_data / time if args.data_dir is None else Path(args.data_dir) else: - print("Run Benchmark: Connected to remote host " + args.hostname + ".") + # Step 2: Connect to remote + if not host_connect_to_remote(args): + print("Run Benchmark: Cannot connect to host! Abort.") + sys.exit(1) + else: + print("Run Benchmark: Connected to remote host " + args.hostname + ".") - # Step 3 (skipped). - remote_execute_cmd("hostname") + # Step 3 (skipped). + remote_execute_cmd("hostname") - # Step 4.1. + # Step 4.1: Compile LF files on host selected = None excluded = [] if args.select is not None: @@ -551,85 +659,107 @@ def main(args=None): host_rm_dir(host_src_gen) host_compile_lf_files_in_dir(args, host_src, selected, excluded) - # Step 4.2. - if not args.no_scp: - remote_rm_dir(remost_dest) - remote_create_dir(remost_dest) - if (args.platform != "RPI4-QNX"): - host_forall_subdirs_do(host_scp_dir, host_src_gen, remost_dest, args, True) - - # Step 4.3 - if not args.no_cmake: - if (args.platform != "RPI4-QNX"): - remote_forall_subdirs_do(remote_compile_cmake_project, remost_dest) - else: - # If an existing host_bin directory exists, remove it. - # Otherwise, binaries from previous runs could persist - # and get scp-ed to the remote target mistakenly. - host_rm_dir(host_bin) - # Cross compile the LF programs, which puts binaries in host_bin - host_cross_compile_qnx_lf_files_in_dir(args, host_src_gen) - # Secure copy the generated file from host_bin to the remote host - host_scp_exec_files(host_bin, remost_dest, args) - - # Step 4.4 - # Skipped. Assuming tracing is in use - - if not args.no_run: - # Step 4.5: run programs and collect trace files in a remote data directory. - remote_rm_dir(remote_data) - remote_create_dir(remote_data) - if (args.platform != "RPI4-QNX"): - remote_forall_subdirs_do(func=remote_run_program, dir=remost_dest, arg1=remote_data, arg2=args) - else: - remote_run_all_programs_qnx(remost_dest, remote_data) - - # Step 4.6: run tracing remotely, if not a QNX platform - if not args.no_tracing: - if (args.platform != "RPI4-QNX"): + if is_local: + # LOCAL MODE: Compile and run locally + + # Step 4.3: Compile CMake projects locally + if not args.no_cmake: + host_forall_subdirs_do(local_compile_cmake_project, host_src_gen) + + if not args.no_run: + # Step 4.5: Run programs locally and collect trace files + host_create_dir(local_data) + host_forall_subdirs_do(func=local_run_program, dir=host_src_gen, arg1=str(local_data), arg2=args) + + # Step 4.6: Run trace conversion locally + if not args.no_tracing: convert_for_chrome = True - remote_forall_files_in_dir_do(remote_run_trace_conversion, remote_data, remote_data, convert_for_chrome) - - # Step 4.7 - host_create_dir(host_data) + # Find and convert all .lft files in the local data directory + for lft_file in os.listdir(local_data): + if lft_file.endswith(".lft"): + local_run_trace_conversion(lft_file, str(local_data), convert_for_chrome) + else: + # REMOTE MODE: Original behavior - if args.data_dir is None: - data_entry_dir = host_data / time - else: - data_entry_dir = args.data_dir - host_scp_dir(remote_data, data_entry_dir, args, from_host_to_remote=False) + # Step 4.2. + if not args.no_scp: + remote_rm_dir(remost_dest) + remote_create_dir(remost_dest) + if (args.platform != "RPI4-QNX"): + host_forall_subdirs_do(host_scp_dir, host_src_gen, remost_dest, args, True) + + # Step 4.3 + if not args.no_cmake: + if (args.platform != "RPI4-QNX"): + remote_forall_subdirs_do(remote_compile_cmake_project, remost_dest) + else: + # If an existing host_bin directory exists, remove it. + # Otherwise, binaries from previous runs could persist + # and get scp-ed to the remote target mistakenly. + host_rm_dir(host_bin) + # Cross compile the LF programs, which puts binaries in host_bin + host_cross_compile_qnx_lf_files_in_dir(args, host_src_gen) + # Secure copy the generated file from host_bin to the remote host + host_scp_exec_files(host_bin, remost_dest, args) + + # Step 4.4 + # Skipped. Assuming tracing is in use + + if not args.no_run: + # Step 4.5: run programs and collect trace files in a remote data directory. + remote_rm_dir(remote_data) + remote_create_dir(remote_data) + if (args.platform != "RPI4-QNX"): + remote_forall_subdirs_do(func=remote_run_program, dir=remost_dest, arg1=remote_data, arg2=args) else: - # Step 4.7 + remote_run_all_programs_qnx(remost_dest, remote_data) + + # Step 4.6: run tracing remotely, if not a QNX platform + if not args.no_tracing: + if (args.platform != "RPI4-QNX"): + convert_for_chrome = True + remote_forall_files_in_dir_do(remote_run_trace_conversion, remote_data, remote_data, convert_for_chrome) + + # Step 4.7 + host_create_dir(host_data) + + if args.data_dir is None: + data_entry_dir = host_data / time + else: + data_entry_dir = args.data_dir + host_scp_dir(remote_data, data_entry_dir, args, from_host_to_remote=False) + else: + # Step 4.7 + if args.data_dir is None: + data_entry_dir = host_data / time + else: + data_entry_dir = args.data_dir + host_scp_dir(remote_data, data_entry_dir, args, from_host_to_remote=False) + + # Now, run trace-to-csv on the host + # Note that files were transformed as txt files + os.chdir(data_entry_dir) + for txt_file in os.listdir(data_entry_dir): + if txt_file.endswith(".txt"): + lft_file = os.path.splitext(txt_file)[0] + ".lft" + # Rename the file + os.rename(txt_file, lft_file) + # Now, run trace_to_csv + cmd = ["trace_to_csv", lft_file] + host_execute_cmd(cmd) + print("Converted: " + lft_file) + + # If this is true, we are doing performance benchmarking. + # Copy the txt file back to host. + elif args.repeat > 0: if args.data_dir is None: data_entry_dir = host_data / time else: data_entry_dir = args.data_dir host_scp_dir(remote_data, data_entry_dir, args, from_host_to_remote=False) - # Now, run trace-to-csv on the host - # Note that files were transformed as txt files - os.chdir(data_entry_dir) - for txt_file in os.listdir(data_entry_dir): - if txt_file.endswith(".txt"): - lft_file = os.path.splitext(txt_file)[0] + ".lft" - # Rename the file - os.rename(txt_file, lft_file) - # Now, run trace_to_csv - cmd = ["trace_to_csv", lft_file] - host_execute_cmd(cmd) - print("Converted: " + lft_file) - - # If this is true, we are doing performance benchmarking. - # Copy the txt file back to host. - elif args.repeat > 0: - if args.data_dir is None: - data_entry_dir = host_data / time - else: - data_entry_dir = args.data_dir - host_scp_dir(remote_data, data_entry_dir, args, from_host_to_remote=False) - - # Step 4.8 - host_close_connection_to_remote() + # Step 4.8 + host_close_connection_to_remote() # Step 5: Post-Processing if args.post_analysis is not None: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..42ea071 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: '3.8' + +services: + emsoft25: + build: + context: . + dockerfile: Dockerfile + image: emsoft25:local + container_name: emsoft25-benchmarks + volumes: + - .:/workspace + working_dir: /workspace + stdin_open: true + tty: true + command: /bin/bash