Adding scripts, commands, and logging scaffolding"
This commit is contained in:
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# keep logs; ignore the heavyweight gem5 artifacts if they get huge
|
||||
results/*/m5out
|
||||
results/*/config.json
|
||||
results/*/config.ini.bak
|
||||
results/*/*.checkpoints/
|
||||
# but DO NOT ignore stats or figures:
|
||||
!results/*/stats.txt
|
||||
!results/*.csv
|
||||
!results/*.png
|
||||
|
||||
# python cache
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# SmartEdgeAI - (gem5)
|
||||
|
||||
This repo holds **all scripts, commands, and logs** for Phase 3.
|
||||
|
||||
## Order of operations
|
||||
1) `scripts/00_env.sh` – sets env vars used by all scripts
|
||||
2) `scripts/10_run_one.sh` – run a single experiment with clear args
|
||||
3) `scripts/20_sweep.sh` – run the full matrix
|
||||
4) `scripts/30_extract_csv.sh` – collect gem5 stats → CSV
|
||||
5) `scripts/40_energy_post.py` – compute Energy/Power/**EDP=J×s**
|
||||
6) `scripts/50_plot_epi.py` / `scripts/51_plot_edp_tinyml.py` – figures
|
||||
7) `scripts/60_bundle_logs.sh` – bundle terminal + stats excerpts
|
||||
8) (optional) `scripts/70_diff_table.py` – drowsy vs non-drowsy deltas
|
||||
|
||||
## Paths assumed
|
||||
- gem5 binary: `../../build/ARM/gem5.opt`
|
||||
- config: `../../scripts/hetero_big_little.py`
|
||||
- workloads: `../../gem5-run/{tinyml_kws,sensor_fusion,aes_ccm,attention_kernel}`
|
||||
|
||||
All output is under `iot/results` and `iot/logs`.
|
||||
|
||||
0
logs/STATS_EXCERPTS.txt
Normal file
0
logs/STATS_EXCERPTS.txt
Normal file
0
logs/TERMINAL_EXCERPTS.txt
Normal file
0
logs/TERMINAL_EXCERPTS.txt
Normal file
0
results/fig_epi_across_workloads.png
Normal file
0
results/fig_epi_across_workloads.png
Normal file
0
results/fig_tinyml_edp.png
Normal file
0
results/fig_tinyml_edp.png
Normal file
0
results/summary.csv
Normal file
0
results/summary.csv
Normal file
|
|
0
results/summary_energy.csv
Normal file
0
results/summary_energy.csv
Normal file
|
|
21
scripts/00_env.sh
Normal file
21
scripts/00_env.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/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"
|
||||
|
||||
mkdir -p "$OUTROOT" "$LOGROOT"
|
||||
|
||||
# record environment (append-only)
|
||||
{
|
||||
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] READY"
|
||||
|
||||
27
scripts/10_run_one.sh
Normal file
27
scripts/10_run_one.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
source "$(dirname "$0")/00_env.sh"
|
||||
|
||||
if [[ $# -lt 5 ]]; then
|
||||
echo "Usage: $0 <workload:{tinyml_kws|sensor_fusion|aes_ccm|attention_kernel}> <core:{big|little|hybrid}> <dvfs:{high|low}> <drowsy:{0|1}> <l2:{512kB|1MB}> [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}"
|
||||
|
||||
mkdir -p "$OUT"
|
||||
echo "[run_one] $W $CORE $DV L2=$L2 drowsy=$DROWSY mem=$MEM -> $OUT"
|
||||
|
||||
"$GEM5" "$CFG" \
|
||||
--cmd="$RUN/$W" \
|
||||
--mem="$MEM" \
|
||||
--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"
|
||||
|
||||
echo "[run_one] DONE"
|
||||
|
||||
23
scripts/20_sweep.sh
Normal file
23
scripts/20_sweep.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
source "$(dirname "$0")/00_env.sh"
|
||||
|
||||
run_case () {
|
||||
local W=$1 CORE=$2 DV=$3 D=$4 L2=$5 MEM=16GB
|
||||
bash "$(dirname "$0")/10_run_one.sh" "$W" "$CORE" "$DV" "$D" "$L2" "$MEM"
|
||||
}
|
||||
|
||||
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 "[sweep] ALL DONE"
|
||||
|
||||
28
scripts/30_extract_csv.sh
Normal file
28
scripts/30_extract_csv.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
source "$(dirname "$0")/00_env.sh"
|
||||
|
||||
CSV="$OUTROOT/phase3_summary.csv"
|
||||
echo "workload,core,dvfs,l2,drowsy,sim_seconds,ipc,cycles,insts,l2_miss_rate" > "$CSV"
|
||||
|
||||
for d in "$OUTROOT"/*; do
|
||||
[[ -d "$d" ]] || continue
|
||||
base=$(basename "$d")
|
||||
W=$(echo "$base" | cut -d'_' -f1)
|
||||
CORE=$(echo "$base" | cut -d'_' -f2)
|
||||
DVFS=$(echo "$base" | cut -d'_' -f3)
|
||||
L2=$(echo "$base" | sed -E 's/.*_l2([^_]+).*/\1/')
|
||||
DROW=$(echo "$base" | sed -E 's/.*_d([01]).*/\1/')
|
||||
S="$d/stats.txt"
|
||||
|
||||
SIMS=$(awk '/^sim_seconds/ {print $2}' "$S")
|
||||
IPC=$(awk '/^system\.cpu\.ipc|^system\.cpu0\.ipc/ {print $2}' "$S" | head -n1)
|
||||
CYC=$(awk '/^system\.cpu\.numCycles|^system\.cpu0\.numCycles/ {print $2}' "$S" | head -n1)
|
||||
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"
|
||||
done
|
||||
|
||||
echo "[extract] wrote $CSV"
|
||||
|
||||
48
scripts/40_energy_post.py
Normal file
48
scripts/40_energy_post.py
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
import csv, sys, os
|
||||
|
||||
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")
|
||||
|
||||
# === 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
|
||||
|
||||
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'])
|
||||
|
||||
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:
|
||||
energy_J *= DROWSY_SCALE
|
||||
|
||||
power_W = energy_J / secs if secs > 0 else 0.0
|
||||
edp = energy_J * secs # CORRECT EDP
|
||||
|
||||
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}",
|
||||
})
|
||||
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}")
|
||||
|
||||
28
scripts/50_plot_epi.py
Normal file
28
scripts/50_plot_epi.py
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
import csv, os
|
||||
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")
|
||||
|
||||
epi_by_core = defaultdict(list)
|
||||
with open(src) as f:
|
||||
r=csv.DictReader(f)
|
||||
for row in r:
|
||||
insts=float(row['insts']); energy=float(row['energy_J'])
|
||||
epi = 1e12*energy/insts if insts>0 else 0.0
|
||||
epi_by_core[row['core']].append(epi)
|
||||
|
||||
cores=['big','little','hybrid']
|
||||
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}")
|
||||
|
||||
25
scripts/51_plot_edp_tinyml.py
Normal file
25
scripts/51_plot_edp_tinyml.py
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
import csv, os
|
||||
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")
|
||||
|
||||
labels=[]; edps=[]
|
||||
with open(src) as f:
|
||||
r=csv.DictReader(f)
|
||||
for row in r:
|
||||
if row['workload']!='tinyml_kws': continue
|
||||
labels.append(f"{row['core']}-{row['dvfs']}-L2{row['l2']}-d{row['drowsy']}")
|
||||
edps.append(float(row['edp']))
|
||||
|
||||
plt.figure()
|
||||
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}")
|
||||
|
||||
23
scripts/60_bundle_logs.sh
Normal file
23
scripts/60_bundle_logs.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
source "$(dirname "$0")/00_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"
|
||||
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"
|
||||
done
|
||||
echo "[bundle] wrote $LOGROOT/STATS_EXCERPTS.txt"
|
||||
|
||||
34
scripts/70_diff_table.py
Normal file
34
scripts/70_diff_table.py
Normal file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
import csv, os
|
||||
root = os.path.dirname(os.path.dirname(__file__))
|
||||
src = os.path.join(root, "results", "phase3_summary_energy.csv")
|
||||
dst = os.path.join(root, "results", "phase3_drowsy_deltas.csv")
|
||||
|
||||
# group by key without drowsy; compare d0 vs d1
|
||||
from collections import defaultdict
|
||||
bykey = defaultdict(dict)
|
||||
|
||||
with open(src) as f:
|
||||
r=csv.DictReader(f)
|
||||
for row in r:
|
||||
key = (row['workload'], row['core'], row['dvfs'], row['l2'])
|
||||
bykey[key][row['drowsy']] = row
|
||||
|
||||
rows=[]
|
||||
for k, d in bykey.items():
|
||||
if '0' in d and '1' in d:
|
||||
a=d['0']; b=d['1']
|
||||
e0=float(a['energy_J']); e1=float(b['energy_J'])
|
||||
edp0=float(a['edp']); edp1=float(b['edp'])
|
||||
rows.append({
|
||||
'workload':k[0],'core':k[1],'dvfs':k[2],'l2':k[3],
|
||||
'energy_drop_%': f"{100*(e0-e1)/e0:.2f}",
|
||||
'edp_drop_%': f"{100*(edp0-edp1)/edp0:.2f}"
|
||||
})
|
||||
|
||||
with open(dst,'w',newline='') as f:
|
||||
w=csv.DictWriter(f, fieldnames=list(rows[0].keys()))
|
||||
w.writeheader(); w.writerows(rows)
|
||||
|
||||
print(f"[delta] wrote {dst}")
|
||||
|
||||
Reference in New Issue
Block a user