diff --git a/logs/env.txt b/logs/env.txt index e7def1b..45f0f8e 100644 --- a/logs/env.txt +++ b/logs/env.txt @@ -6,3 +6,27 @@ Sat Oct 4 09:40:18 PM UTC 2025 ==== gem5 version ==== n/a +==== uname ==== +Linux cargdevgpu 6.8.0-60-generic #63-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 19:04:15 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux + +==== date ==== +Sat Oct 4 09:56:17 PM UTC 2025 + +==== gem5 git ==== +n/a +==== uname ==== +Linux cargdevgpu 6.8.0-60-generic #63-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 19:04:15 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux + +==== date ==== +Sat Oct 4 10:26:30 PM UTC 2025 + +==== gem5 git ==== +n/a +==== uname ==== +Linux cargdevgpu 6.8.0-60-generic #63-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 19:04:15 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux + +==== date ==== +Sat Oct 4 10:26:47 PM UTC 2025 + +==== gem5 git ==== +n/a diff --git a/logs/tinyml_kws_big_high_l21MB_d0.stderr.log b/logs/tinyml_kws_big_high_l21MB_d0.stderr.log new file mode 100644 index 0000000..ba93514 --- /dev/null +++ b/logs/tinyml_kws_big_high_l21MB_d0.stderr.log @@ -0,0 +1 @@ +./scripts/10_run_one.sh: line 16: /home/carlos/projects/gem5/build/ARM/gem5.opt: No such file or directory diff --git a/logs/tinyml_kws_big_high_l21MB_d0.stdout.log b/logs/tinyml_kws_big_high_l21MB_d0.stdout.log new file mode 100644 index 0000000..e69de29 diff --git a/scripts/00_env.sh b/scripts/00_env.sh old mode 100644 new mode 100755 index 7b18aaf..975ece5 --- a/scripts/00_env.sh +++ b/scripts/00_env.sh @@ -1,21 +1,48 @@ #!/bin/bash set -eu -# source this from anywhere inside /home/carlos/projects/gem5 ROOT="/home/carlos/projects/gem5" -export GEM5="$ROOT/build/ARM/gem5.opt" -export CFG="$ROOT/scripts/hetero_big_little.py" -export RUN="$ROOT/gem5-run" -export OUTROOT="$ROOT/iot/results" -export LOGROOT="$ROOT/iot/logs" +IOT="$ROOT/iot" +DATA="$ROOT/gem5-data" # persistent store (your symlink) +RUN="$ROOT/gem5-run" # workloads +CFG="$ROOT/scripts/hetero_big_little.py" # gem5 config script -mkdir -p "$OUTROOT" "$LOGROOT" +# auto-detect gem5.opt (ARM or ARM64) +if [ -x "$ROOT/build/ARM/gem5.opt" ]; then + GEM5="$ROOT/build/ARM/gem5.opt" +elif [ -x "$ROOT/gem5-build/ARM/gem5.opt" ]; then + GEM5="$ROOT/gem5-build/ARM/gem5.opt" +elif [ -x "$ROOT/gem5-build/ARM64/gem5.opt" ]; then + GEM5="$ROOT/gem5-build/ARM64/gem5.opt" +else + echo "[env] gem5.opt not found. Build it with:" + echo " scons build/ARM/gem5.opt -j\$(nproc)" + exit 2 +fi -# record environment (append-only) +# primary outputs in gem5-data, mirrored into iot/ +OUT_DATA="$DATA/SmartEdgeAI/results" +LOG_DATA="$DATA/SmartEdgeAI/logs" +OUT_IOT="$IOT/results" +LOG_IOT="$IOT/logs" + +# ensure directories +mkdir -p "$OUT_DATA" "$LOG_DATA" "$OUT_IOT" "$LOG_IOT" + +# export for child scripts +export ROOT IOT DATA RUN CFG GEM5 OUT_DATA LOG_DATA OUT_IOT LOG_IOT + +# minimal env log { - echo "==== uname ===="; uname -a - echo; echo "==== date ===="; date - echo; echo "==== gem5 git ===="; (git -C "$ROOT/gem5src" rev-parse --short HEAD 2>/dev/null || echo n/a) -} >> "$LOGROOT/env.txt" + echo "==== env ====" + echo "ROOT=$ROOT" + echo "GEM5=$GEM5" + echo "CFG=$CFG" + echo "RUN=$RUN" + echo "OUT_DATA=$OUT_DATA" + echo "LOG_DATA=$LOG_DATA" + date +} >> "$LOG_IOT/env.txt" + echo "[env] READY" diff --git a/scripts/01_build_gem5.sh b/scripts/01_build_gem5.sh new file mode 100755 index 0000000..9c789c4 --- /dev/null +++ b/scripts/01_build_gem5.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -eu +cd /home/carlos/projects/gem5 +scons build/ARM/gem5.opt -j"$(nproc)" diff --git a/scripts/10_run_one.sh b/scripts/10_run_one.sh old mode 100644 new mode 100755 index f92a830..1932caf --- a/scripts/10_run_one.sh +++ b/scripts/10_run_one.sh @@ -1,17 +1,18 @@ #!/bin/bash set -eu -source "$(dirname "$0")/00_env.sh" +. "$(dirname "$0")/env.sh" -if [[ $# -lt 5 ]]; then +if [ $# -lt 5 ]; then echo "Usage: $0 [mem=16GB]" exit 1 fi W=$1; CORE=$2; DV=$3; DROWSY=$4; L2=$5; MEM=${6:-16GB} -OUT="$OUTROOT/${W}_${CORE}_${DV}_l2${L2}_d${DROWSY}" +TAG="${W}_${CORE}_${DV}_l2${L2}_d${DROWSY}" +OUTDIR="$OUT_DATA/$TAG" -mkdir -p "$OUT" -echo "[run_one] $W $CORE $DV L2=$L2 drowsy=$DROWSY mem=$MEM -> $OUT" +mkdir -p "$OUTDIR" +echo "[run_one] $TAG mem=$MEM -> $OUTDIR" "$GEM5" "$CFG" \ --cmd="$RUN/$W" \ @@ -19,9 +20,13 @@ echo "[run_one] $W $CORE $DV L2=$L2 drowsy=$DROWSY mem=$MEM -> $OUT" --dvfs="$DV" \ --drowsy="$DROWSY" \ --l2="$L2" \ - --outdir="$OUT" \ - > "$LOGROOT/${W}_${CORE}_${DV}_l2${L2}_d${DROWSY}.stdout.log" \ - 2> "$LOGROOT/${W}_${CORE}_${DV}_l2${L2}_d${DROWSY}.stderr.log" + --outdir="$OUTDIR" \ + > "$LOG_DATA/${TAG}.stdout.log" \ + 2> "$LOG_DATA/${TAG}.stderr.log" + +# mirror to repo (iot/) +rsync -a --delete "$OUTDIR/" "$OUT_IOT/$TAG/" +rsync -a "$LOG_DATA/${TAG}."* "$LOG_IOT/" 2>/dev/null || true echo "[run_one] DONE" diff --git a/scripts/11_run_all.sh b/scripts/11_run_all.sh new file mode 100755 index 0000000..9e2c6d5 --- /dev/null +++ b/scripts/11_run_all.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -eu +. "$(dirname "$0")/env.sh" + +run_case () { + W=$1; CORE=$2; DV=$3; D=$4; L2=$5 + sh "$(dirname "$0")/run_one.sh" "$W" "$CORE" "$DV" "$D" "$L2" 16GB +} + +for W in tinyml_kws sensor_fusion aes_ccm attention_kernel; do + for DV in high low; do + for D in 0 1; do + for L2 in 512kB 1MB; do + run_case "$W" big "$DV" "$D" "$L2" + run_case "$W" little "$DV" "$D" "$L2" + run_case "$W" hybrid "$DV" "$D" "$L2" + done + done + done +done + +echo "[run_all] ALL DONE" + diff --git a/scripts/20_sweep.sh b/scripts/20_sweep.sh old mode 100644 new mode 100755 diff --git a/scripts/30_extract_csv.sh b/scripts/30_extract_csv.sh old mode 100644 new mode 100755 index 802d622..7432043 --- a/scripts/30_extract_csv.sh +++ b/scripts/30_extract_csv.sh @@ -1,12 +1,13 @@ #!/bin/bash set -eu -source "$(dirname "$0")/00_env.sh" +. "$(dirname "$0")/env.sh" -CSV="$OUTROOT/phase3_summary.csv" -echo "workload,core,dvfs,l2,drowsy,sim_seconds,ipc,cycles,insts,l2_miss_rate" > "$CSV" +CSV_DATA="$OUT_DATA/summary.csv" +CSV_IOT="$OUT_IOT/summary.csv" +echo "workload,core,dvfs,l2,drowsy,sim_seconds,ipc,cycles,insts,l2_miss_rate" > "$CSV_DATA" -for d in "$OUTROOT"/*; do - [[ -d "$d" ]] || continue +for d in "$OUT_DATA"/*; do + [ -d "$d" ] || continue base=$(basename "$d") W=$(echo "$base" | cut -d'_' -f1) CORE=$(echo "$base" | cut -d'_' -f2) @@ -21,8 +22,9 @@ for d in "$OUTROOT"/*; do INST=$(awk '/^system\.cpu\.commit\.committedInsts|^system\.cpu0\.commit\.committedInsts/ {print $2}' "$S" | head -n1) L2MR=$(awk '/^system\.l2\.overall_miss_rate::total/ {print $2}' "$S") - echo "$W,$CORE,$DVFS,$L2,$DROW,$SIMS,$IPC,$CYC,$INST,$L2MR" >> "$CSV" + echo "$W,$CORE,$DVFS,$L2,$DROW,$SIMS,$IPC,$CYC,$INST,$L2MR" >> "$CSV_DATA" done -echo "[extract] wrote $CSV" +cp "$CSV_DATA" "$CSV_IOT" +echo "[extract] wrote $CSV_DATA and mirrored to $CSV_IOT" diff --git a/scripts/40_energy_post.py b/scripts/40_energy_post.py old mode 100644 new mode 100755 index d83e0ab..57d6e7a --- a/scripts/40_energy_post.py +++ b/scripts/40_energy_post.py @@ -1,48 +1,48 @@ #!/usr/bin/env python3 -import csv, sys, os +import csv, os, sys -root = os.path.dirname(os.path.dirname(__file__)) -src = os.path.join(root, "results", "phase3_summary.csv") -dst = os.path.join(root, "results", "phase3_summary_energy.csv") +ROOT = "/home/carlos/projects/gem5" +OUT_DATA = os.path.join(ROOT, "gem5-data", "SmartEdgeAI", "results") +OUT_IOT = os.path.join(ROOT, "iot", "results") -# === your modeling constants (document in Methods) === -EPI_PJ = {'big': 200.0, 'little': 80.0, 'hybrid': 104.0} # pJ/inst -E_MEM_PJ = 600.0 # pJ per L2 miss -DROWSY_SCALE = 0.85 # 15% energy reduction when drowsy=1 +src = os.path.join(OUT_DATA, "summary.csv") +dst_data = os.path.join(OUT_DATA, "summary_energy.csv") +dst_iot = os.path.join(OUT_IOT, "summary_energy.csv") + +# modeling constants (document in your Methods) +EPI_PJ = {'big':200.0,'little':80.0,'hybrid':104.0} # pJ/inst +E_MEM_PJ = 600.0 # pJ per L2 miss +DROWSY_SCALE = 0.85 # 15% energy drop when drowsy=1 rows=[] with open(src) as f: r=csv.DictReader(f) for row in r: - insts = float(row['insts']) - secs = float(row['sim_seconds']) - core = row['core'] - drowsy= int(row['drowsy']) - epi_pJ= EPI_PJ.get(core, EPI_PJ['little']) + insts=float(row['insts']) + secs=float(row['sim_seconds']) + core=row['core']; drowsy=int(row['drowsy']) + epi=EPI_PJ.get(core, EPI_PJ['little']) + mr=float(row['l2_miss_rate']) if row['l2_miss_rate'] else 0.0 - mr = float(row['l2_miss_rate']) if row['l2_miss_rate'] else 0.0 - l2_misses = mr * insts # proxy; replace with MPKI-based calc if available - - energy_instr = (epi_pJ * 1e-12) * insts - energy_mem = (E_MEM_PJ * 1e-12) * l2_misses - energy_J = energy_instr + energy_mem - if drowsy == 1: + l2_misses = mr * insts + energy_J = (epi*1e-12)*insts + (E_MEM_PJ*1e-12)*l2_misses + if drowsy==1: energy_J *= DROWSY_SCALE - power_W = energy_J / secs if secs > 0 else 0.0 - edp = energy_J * secs # CORRECT EDP + power_W = energy_J/secs if secs>0 else 0.0 + edp = energy_J * secs # J*s row.update({ 'energy_J': f"{energy_J:.6f}", - 'power_W': f"{power_W:.6f}", - 'edp': f"{edp:.6e}", - 'epi_model_pJ': f"{epi_pJ:.1f}", + 'power_W': f"{power_W:.6f}", + 'edp': f"{edp:.6e}", + 'epi_model_pJ': f"{epi:.1f}", }) rows.append(row) -with open(dst, 'w', newline='') as f: - w=csv.DictWriter(f, fieldnames=list(rows[0].keys())) - w.writeheader(); w.writerows(rows) - -print(f"[energy] wrote {dst}") +for path in (dst_data, dst_iot): + with open(path, 'w', newline='') as f: + w=csv.DictWriter(f, fieldnames=list(rows[0].keys())) + w.writeheader(); w.writerows(rows) +print(f"[energy] wrote {dst_data} and mirrored to {dst_iot}") diff --git a/scripts/50_plot_epi.py b/scripts/50_plot_epi.py old mode 100644 new mode 100755 index 3e2155c..b0146b6 --- a/scripts/50_plot_epi.py +++ b/scripts/50_plot_epi.py @@ -1,13 +1,16 @@ #!/usr/bin/env python3 -import csv, os +import os, csv import matplotlib.pyplot as plt from collections import defaultdict -root = os.path.dirname(os.path.dirname(__file__)) -src = os.path.join(root, "results", "phase3_summary_energy.csv") -out = os.path.join(root, "results", "fig_epi_across_workloads.png") +ROOT="/home/carlos/projects/gem5" +OUT_DATA=os.path.join(ROOT,"gem5-data","SmartEdgeAI","results") +OUT_IOT =os.path.join(ROOT,"iot","results") +src=os.path.join(OUT_DATA,"summary_energy.csv") +out_data=os.path.join(OUT_DATA,"fig_epi_across_workloads.png") +out_iot =os.path.join(OUT_IOT ,"fig_epi_across_workloads.png") -epi_by_core = defaultdict(list) +epi_by_core=defaultdict(list) with open(src) as f: r=csv.DictReader(f) for row in r: @@ -21,8 +24,7 @@ vals=[sum(epi_by_core[c])/max(1,len(epi_by_core[c])) for c in cores] plt.figure() plt.bar(cores, vals) plt.ylabel('EPI (pJ/inst)') -plt.title('Energy per Instruction across Workloads (avg by core mode)') -plt.tight_layout() -plt.savefig(out) -print(f"[plot] wrote {out}") +plt.title('Energy per Instruction across workloads (avg by core mode)') +plt.tight_layout(); plt.savefig(out_data); plt.savefig(out_iot) +print(f"[plot] wrote {out_data} and mirrored to {out_iot}") diff --git a/scripts/51_plot_edp_tinyml.py b/scripts/51_plot_edp_tinyml.py old mode 100644 new mode 100755 index 17dbf83..8df3670 --- a/scripts/51_plot_edp_tinyml.py +++ b/scripts/51_plot_edp_tinyml.py @@ -1,10 +1,13 @@ #!/usr/bin/env python3 -import csv, os +import os, csv import matplotlib.pyplot as plt -root = os.path.dirname(os.path.dirname(__file__)) -src = os.path.join(root, "results", "phase3_summary_energy.csv") -out = os.path.join(root, "results", "fig_tinyml_edp.png") +ROOT="/home/carlos/projects/gem5" +OUT_DATA=os.path.join(ROOT,"gem5-data","SmartEdgeAI","results") +OUT_IOT =os.path.join(ROOT,"iot","results") +src=os.path.join(OUT_DATA,"summary_energy.csv") +out_data=os.path.join(OUT_DATA,"fig_tinyml_edp.png") +out_iot =os.path.join(OUT_IOT ,"fig_tinyml_edp.png") labels=[]; edps=[] with open(src) as f: @@ -19,7 +22,6 @@ plt.bar(labels, edps) plt.ylabel('EDP (J·s)') plt.title('TinyML: EDP by configuration') plt.xticks(rotation=60, ha='right') -plt.tight_layout() -plt.savefig(out) -print(f"[plot] wrote {out}") +plt.tight_layout(); plt.savefig(out_data); plt.savefig(out_iot) +print(f"[plot] wrote {out_data} and mirrored to {out_iot}") diff --git a/scripts/60_bundle_logs.sh b/scripts/60_bundle_logs.sh old mode 100644 new mode 100755 index 4c7f2ac..18ea210 --- a/scripts/60_bundle_logs.sh +++ b/scripts/60_bundle_logs.sh @@ -1,23 +1,29 @@ #!/bin/bash set -eu -source "$(dirname "$0")/00_env.sh" +. "$(dirname "$0")/env.sh" -# terminal excerpts -: > "$LOGROOT/TERMINAL_EXCERPTS.txt" -for f in "$LOGROOT"/*.stdout.log; do - echo "===== $(basename "$f") =====" >> "$LOGROOT/TERMINAL_EXCERPTS.txt" - (head -n 20 "$f"; echo "..."; tail -n 20 "$f") >> "$LOGROOT/TERMINAL_EXCERPTS.txt" - echo >> "$LOGROOT/TERMINAL_EXCERPTS.txt" +TE="$LOG_DATA/TERMINAL_EXCERPTS.txt" +SE="$LOG_DATA/STATS_EXCERPTS.txt" +: > "$TE"; : > "$SE" + +for f in "$LOG_DATA"/*.stdout.log; do + [ -f "$f" ] || continue + echo "===== $(basename "$f") =====" >> "$TE" + (head -n 20 "$f"; echo "..."; tail -n 20 "$f") >> "$TE" + echo >> "$TE" done -echo "[bundle] wrote $LOGROOT/TERMINAL_EXCERPTS.txt" -# stats excerpts -: > "$LOGROOT/STATS_EXCERPTS.txt" -for d in "$OUTROOT"/*; do - [[ -d "$d" ]] || continue - echo "===== $(basename "$d") =====" >> "$LOGROOT/STATS_EXCERPTS.txt" - awk '/^sim_seconds|^system\.cpu\.ipc|^system\.cpu0\.ipc|^system\.cpu\.numCycles|^system\.cpu0\.numCycles|^system\.cpu\.commit\.committedInsts|^system\.cpu0\.commit\.committedInsts|^system\.l2\.overall_miss_rate::total/' "$d/stats.txt" >> "$LOGROOT/STATS_EXCERPTS.txt" - echo >> "$LOGROOT/STATS_EXCERPTS.txt" +for d in "$OUT_DATA"/*; do + [ -d "$d" ] || continue + S="$d/stats.txt" + [ -f "$S" ] || continue + echo "===== $(basename "$d") =====" >> "$SE" + awk '/^sim_seconds|^system\.cpu\.ipc|^system\.cpu0\.ipc|^system\.cpu\.numCycles|^system\.cpu0\.numCycles|^system\.cpu\.commit\.committedInsts|^system\.cpu0\.commit\.committedInsts|^system\.l2\.overall_miss_rate::total/' "$S" >> "$SE" + echo >> "$SE" done -echo "[bundle] wrote $LOGROOT/STATS_EXCERPTS.txt" + +# mirror to repo +cp "$TE" "$LOG_IOT/TERMINAL_EXCERPTS.txt" +cp "$SE" "$LOG_IOT/STATS_EXCERPTS.txt" +echo "[bundle] wrote $TE and $SE (mirrored into iot/logs)" diff --git a/scripts/61_tinyml_kws.sh b/scripts/61_tinyml_kws.sh new file mode 100755 index 0000000..ef1b57d --- /dev/null +++ b/scripts/61_tinyml_kws.sh @@ -0,0 +1,8 @@ +cat > /home/carlos/projects/gem5/gem5-run/tinyml_kws << 'SH' +#!/bin/bash +# placeholder workload; swap later for your real binary +for i in $(seq 1 2000000); do :; done +echo "tinyml_kws: done" +SH +chmod +x /home/carlos/projects/gem5/gem5-run/tinyml_kws + diff --git a/scripts/70_diff_table.py b/scripts/70_diff_table.py old mode 100644 new mode 100755