{ "cells": [ { "cell_type": "markdown", "id": "0daf1763", "metadata": {}, "source": [ "# Get Started with heliaPROFILER\n", "\n", "heliaPROFILER (`hpx`) shows where time, processor events, and memory go when a LiteRT model runs on Ambiq Apollo hardware. It builds and flashes profiling firmware, captures layer-level PMU counters, and returns typed results you can inspect, compare, and export from Python.\n", "\n", "This notebook introduces the interactive `hpx.Session` workflow and highlights the profiler's distinctive capabilities:\n", "\n", "- check host tools and discover boards, probes, ports, engines, and PMU counters;\n", "- branch one immutable experiment into heliaRT and heliaAOT configurations;\n", "- analyze model operations before using hardware;\n", "- capture and filter per-layer cycles and compute-unit counters;\n", "- inspect memory placement, compare engines, and locate Model Explorer overlays;\n", "- add optional Joulescope power measurement without changing the profiling workflow.\n", "\n", "Hardware profiling, probe discovery, and power capture have separate controls. Keep `RUN_HARDWARE = False`, `RUN_PROBE_DISCOVERY = False`, and `RUN_POWER = False` for the safe introductory path. Enable only the operation and hardware you intend to use." ] }, { "cell_type": "markdown", "id": "f1cfa107", "metadata": {}, "source": [ "## 1. Choose Your Run Settings\n", "\n", "Edit the board, transport, and hardware flags in the next cell. RTT is the recommended default and its target sources are bundled with HPX. GCC, CMake, Ninja, and J-Link should already be available to the notebook kernel; the readiness table below reports anything missing.\n", "\n", "See the [transport guide](../../docs/guide/transports.md) for USB CDC, UART, SWO, and advanced RTT overrides." ] }, { "cell_type": "code", "execution_count": 1, "id": "efe83227", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hpx version: 0.1.0\n", "Python: 3.11.15\n", "Model: /Users/adam.page/.cache/helia-profiler/models/tiny-cnn/4419dfff1e15/tiny_cnn.tflite\n", "Transport: rtt\n", "Run hardware: True\n", "Discover probe: True\n", "Capture power: False\n" ] } ], "source": [ "from pathlib import Path\n", "from statistics import mean, median\n", "import csv\n", "import json\n", "import platform\n", "import tempfile\n", "\n", "from rich.console import Console\n", "from rich.table import Table\n", "\n", "import helia_profiler as hpx\n", "\n", "console = Console(highlight=False)\n", "MODEL = hpx.examples.tiny_cnn()\n", "BOARD = \"apollo510_evb\"\n", "TRANSPORT = \"rtt\" # Alternatives: \"usb_cdc\", \"uart\", \"swo\"\n", "RESULTS_ROOT = Path.cwd().resolve() / \"results\" / \"notebook_showcase\"\n", "RT_RESULTS = RESULTS_ROOT / \"helia_rt\"\n", "AOT_RESULTS = RESULTS_ROOT / \"helia_aot\"\n", "COMPARE_RESULTS = RESULTS_ROOT / \"rt_vs_aot\"\n", "EXPORT_DIR = RESULTS_ROOT / \"exports\"\n", "\n", "RUN_HARDWARE = True\n", "RUN_PROBE_DISCOVERY = True\n", "RUN_POWER = False\n", "\n", "print(f\"hpx version: {hpx.__version__}\")\n", "print(f\"Python: {platform.python_version()}\")\n", "print(f\"Model: {MODEL}\")\n", "print(f\"Transport: {TRANSPORT}\")\n", "print(f\"Run hardware: {RUN_HARDWARE}\")\n", "print(f\"Discover probe: {RUN_PROBE_DISCOVERY}\")\n", "print(f\"Capture power: {RUN_POWER}\")" ] }, { "cell_type": "code", "execution_count": 2, "id": "2052bcf2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Base engine: helia-rt\n", "RT engine: helia-rt\n", "AOT engine: helia-aot\n" ] } ], "source": [ "base = (\n", " hpx.Session()\n", " .with_model(MODEL)\n", " .with_target(board=BOARD, toolchain=\"gcc\", transport=TRANSPORT)\n", " .with_profiling(\n", " iterations=100,\n", " warmup=5,\n", " pmu_counters={\"cpu\": \"default\", \"memory\": \"default\"},\n", " )\n", ")\n", "\n", "rt_session = (\n", " base\n", " .with_engine(\"helia-rt\")\n", " .with_model(MODEL, arena_size=131_072)\n", " .with_output(dir=RT_RESULTS, detailed=True)\n", ")\n", "aot_session = (\n", " base\n", " .with_engine(\"helia-aot\")\n", " .with_output(dir=AOT_RESULTS, detailed=True)\n", ")\n", "\n", "print(\"Base engine:\", base.resolve().engine.type)\n", "print(\"RT engine: \", rt_session.resolve().engine.type)\n", "print(\"AOT engine: \", aot_session.resolve().engine.type)\n", "assert base.resolve().engine.type == hpx.EngineType.HELIA_RT" ] }, { "cell_type": "markdown", "id": "83983dd1", "metadata": {}, "source": [ "## 2. Profile the Packaged Example Model\n", "\n", "`hpx.examples.tiny_cnn()` provides a deterministic six-operator int8 CNN with fixed batch size one:\n", "\n", "`Conv2D 3×3 → AveragePool 2×2 → Conv2D 1×1 → Reshape → FullyConnected → Softmax`\n", "\n", "The notebook therefore works from an installed HPX environment without a repository checkout or model download. Future packaged models and companion inputs will also live under `hpx.examples`. `Session.profile()` turns the model into a typed `ProfileResult` through the complete NSX configure, build, flash, capture, and report pipeline." ] }, { "cell_type": "code", "execution_count": 3, "id": "4023690e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Environment Check \n", "╭────┬───────────────────────────────────────────┬───────────┬────────────────────────────────────────────────────╮\n", "│ │ Dependency │ Status │ Location │\n", "├────┼───────────────────────────────────────────┼───────────┼────────────────────────────────────────────────────┤\n", "│ ✓ │ ARM GCC toolchain │ available │ /Applications/ArmGNUToolchain/15.2.rel1/arm-none-… │\n", "│ ✓ │ CMake (>= 3.24) │ available │ /opt/homebrew/bin/cmake │\n", "│ ✓ │ Ninja build system │ available │ /opt/homebrew/bin/ninja │\n", "│ ✓ │ SEGGER J-Link commander │ available │ /usr/local/bin/JLinkExe │\n", "│ ✓ │ neuralspotx Python package │ available │ │\n", "│ ✓ │ pylink Python package (RTT/SWO transport) │ available │ │\n", "│ ✓ │ heliaAOT compiler │ available │ │\n", "│ ✓ │ ARM Compiler (armclang) │ available │ │\n", "│ ✓ │ ARM fromelf (armclang) │ available │ │\n", "│ ✓ │ SEGGER RTT source checkout │ available │ /Users/adam.page/Ambiq/helia/helia-profiler/src/h… │\n", "╰────┴───────────────────────────────────────────┴───────────┴────────────────────────────────────────────────────╯\n", " All required dependencies found. \n", "\n" ], "text/plain": [ "\u001b[1;3mEnvironment Check\u001b[0m\u001b[3m \u001b[0m\n", "╭────┬───────────────────────────────────────────┬───────────┬────────────────────────────────────────────────────╮\n", "│\u001b[1m \u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mDependency \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mStatus \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mLocation \u001b[0m\u001b[1m \u001b[0m│\n", "├────┼───────────────────────────────────────────┼───────────┼────────────────────────────────────────────────────┤\n", "│ \u001b[32m✓\u001b[0m │ ARM GCC toolchain │ available │\u001b[2m \u001b[0m\u001b[2m/Applications/ArmGNUToolchain/15.2.rel1/arm-none-…\u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ CMake (>= 3.24) │ available │\u001b[2m \u001b[0m\u001b[2m/opt/homebrew/bin/cmake \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ Ninja build system │ available │\u001b[2m \u001b[0m\u001b[2m/opt/homebrew/bin/ninja \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ SEGGER J-Link commander │ available │\u001b[2m \u001b[0m\u001b[2m/usr/local/bin/JLinkExe \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ neuralspotx Python package │ available │\u001b[2m \u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ pylink Python package (RTT/SWO transport) │ available │\u001b[2m \u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ heliaAOT compiler │ available │\u001b[2m \u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ ARM Compiler (armclang) │ available │\u001b[2m \u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ ARM fromelf (armclang) │ available │\u001b[2m \u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m│\n", "│ \u001b[32m✓\u001b[0m │ SEGGER RTT source checkout │ available │\u001b[2m \u001b[0m\u001b[2m/Users/adam.page/Ambiq/helia/helia-profiler/src/h…\u001b[0m\u001b[2m \u001b[0m│\n", "╰────┴───────────────────────────────────────────┴───────────┴────────────────────────────────────────────────────╯\n", "\u001b[2;3m \u001b[0m\u001b[2;3;32mAll required dependencies found.\u001b[0m\u001b[2;3m \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"x-ambiq-sdk'...\n",
"\n"
],
"text/plain": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"x-ambiq-sdk'...\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/he\n",
"lia-rt'...\n",
"\n"
],
"text/plain": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/he\n",
"lia-rt'...\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Note: switching to 'c1b97f4a49ab608d226029d1bf1c9c2dac10ef62'.\n",
"\n"
],
"text/plain": [
"Note: switching to 'c1b97f4a49ab608d226029d1bf1c9c2dac10ef62'.\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"You are in 'detached HEAD' state. You can look around, make experimental\n",
"\n"
],
"text/plain": [
"You are in 'detached HEAD' state. You can look around, make experimental\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"changes and commit them, and you can discard any commits you make in this\n",
"\n"
],
"text/plain": [
"changes and commit them, and you can discard any commits you make in this\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"state without impacting any branches by switching back to a branch.\n",
"\n"
],
"text/plain": [
"state without impacting any branches by switching back to a branch.\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"If you want to create a new branch to retain commits you create, you may\n",
"\n"
],
"text/plain": [
"If you want to create a new branch to retain commits you create, you may\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"do so (now or later) by using -c with the switch command. Example:\n",
"\n"
],
"text/plain": [
"do so (now or later) by using -c with the switch command. Example:\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" git switch -c <new-branch-name>\n",
"\n"
],
"text/plain": [
" git switch -c \n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Or undo this operation with:\n",
"\n"
],
"text/plain": [
"Or undo this operation with:\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" git switch -\n",
"\n"
],
"text/plain": [
" git switch -\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Turn off this advice by setting config variable advice.detachedHead to false\n",
"\n"
],
"text/plain": [
"Turn off this advice by setting config variable advice.detachedHead to false\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"-cmsis-nn'...\n",
"\n"
],
"text/plain": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"-cmsis-nn'...\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Note: switching to '2bb81953a20518cf65613bd612352cc462dd7a5e'.\n",
"\n"
],
"text/plain": [
"Note: switching to '2bb81953a20518cf65613bd612352cc462dd7a5e'.\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"You are in 'detached HEAD' state. You can look around, make experimental\n",
"\n"
],
"text/plain": [
"You are in 'detached HEAD' state. You can look around, make experimental\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"changes and commit them, and you can discard any commits you make in this\n",
"\n"
],
"text/plain": [
"changes and commit them, and you can discard any commits you make in this\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"state without impacting any branches by switching back to a branch.\n",
"\n"
],
"text/plain": [
"state without impacting any branches by switching back to a branch.\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"If you want to create a new branch to retain commits you create, you may\n",
"\n"
],
"text/plain": [
"If you want to create a new branch to retain commits you create, you may\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"do so (now or later) by using -c with the switch command. Example:\n",
"\n"
],
"text/plain": [
"do so (now or later) by using -c with the switch command. Example:\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" git switch -c <new-branch-name>\n",
"\n"
],
"text/plain": [
" git switch -c \n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Or undo this operation with:\n",
"\n"
],
"text/plain": [
"Or undo this operation with:\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
" git switch -\n",
"\n"
],
"text/plain": [
" git switch -\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Turn off this advice by setting config variable advice.detachedHead to false\n",
"\n"
],
"text/plain": [
"Turn off this advice by setting config variable advice.detachedHead to false\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Submodule 'Tests/helia-core-tester' (https://github.com/AmbiqAI/helia-core-tester.git) registered for path \n",
"'Tests/helia-core-tester'\n",
"\n"
],
"text/plain": [
"Submodule 'Tests/helia-core-tester' (https://github.com/AmbiqAI/helia-core-tester.git) registered for path \n",
"'Tests/helia-core-tester'\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"-cmsis-nn/Tests/helia-core-tester'...\n",
"\n"
],
"text/plain": [
"Cloning into \n",
"'/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/modules/ns\n",
"-cmsis-nn/Tests/helia-core-tester'...\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Submodule path 'Tests/helia-core-tester': checked out 'bac9cb418ea45becc7af4de394ef3878c8025b42'\n",
"\n"
],
"text/plain": [
"Submodule path 'Tests/helia-core-tester': checked out 'bac9cb418ea45becc7af4de394ef3878c8025b42'\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n",
"\n"
],
"text/plain": [
"/Users/adam.page/Ambiq/helia/helia-profiler/.venv/lib/python3.11/site-packages/rich/live.py:260: UserWarning: \n",
"install \"ipywidgets\" for Jupyter support\n",
" warnings.warn('install \"ipywidgets\" for Jupyter support')\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"[0/2] Re-checking globbed directories...\n",
"[1/2] Flashing hpx_profiler with SEGGER J-Link\n",
"SEGGER J-Link Commander V9.54 (Compiled Jun 25 2026 17:33:57)\n",
"DLL version V9.54, compiled Jun 25 2026 17:33:05\n",
"\n",
"\n",
"J-Link Command File read successfully.\n",
"Processing script file...\n",
"J-Link>ExitOnError 1\n",
"J-Link Commander will now exit on Error\n",
"J-Link>Reset\n",
"J-Link connection not established yet but required for command.\n",
"Connecting to J-Link ...O.K.\n",
"Firmware: J-Link OB-Apollo4-CortexM compiled Feb 5 2026 13:07:52\n",
"Hardware version: V1.00\n",
"J-Link uptime (since boot): 0d 02h 49m 36s\n",
"S/N: 1160002954\n",
"USB speed mode: Full speed (12 MBit/s)\n",
"VTref=1.800V\n",
"Target connection not established yet but required for command.\n",
"Device \"AP510NFA-CBR\" selected.\n",
"\n",
"\n",
"Connecting to target via SWD\n",
"ConfigTargetSettings() start\n",
"Disabling flash programming optimizations: SkipBlankDataOnProg\n",
"ConfigTargetSettings() end - Took 13us\n",
"Found SW-DP with ID 0x4C013477\n",
"DPIDR: 0x4C013477\n",
"CoreSight SoC-600 or later (DPv3 detected)\n",
"Detecting available APs\n",
"APSpace base (BASEPTR0): 0x00000000\n",
"APSpace size (DPIDR1.ASIZE): 12-bit (4 KB)\n",
"AP[0]: Stopped AP scan as end of AP map has been reached\n",
"AP[0] (APAddr 0x00000000): AHB-AP (IDR: 0x34770008)\n",
"Iterating through AP map to find AHB-AP to use\n",
"AP[0]: Core found\n",
"AP[0]: AHB-AP ROM base: 0xE00FE000\n",
"CPUID register: 0x411FD221. Implementer code: 0x41 (ARM)\n",
"Feature set: Mainline\n",
"Cache: L1 I/D-cache present\n",
"Found Cortex-M55 r1p1, Little endian.\n",
"FPUnit: 8 code (BP) slots and 0 literal slots\n",
"Security extension: implemented\n",
"Secure debug: enabled\n",
"PACBTI extension: not implemented\n",
"CoreSight components:\n",
"ROMTbl[0] @ E00FE000\n",
"[0][0]: E00FF000 CID B105100D PID 000BB4D2 DEVARCH 00000000 DEVTYPE 01 ROM Table\n",
"ROMTbl[1] @ E00FF000\n",
"[1][0]: E000E000 CID B105900D PID 000BBD22 DEVARCH 47702A04 DEVTYPE 00 ???\n",
"[1][1]: E0001000 CID B105900D PID 000BBD22 DEVARCH 47711A02 DEVTYPE 00 DWT\n",
"[1][2]: E0002000 CID B105900D PID 000BBD22 DEVARCH 47701A03 DEVTYPE 00 FPB\n",
"[1][3]: E0000000 CID B105900D PID 000BBD22 DEVARCH 47701A01 DEVTYPE 43 ITM\n",
"[1][5]: E0041000 CID B105900D PID 004BBD22 DEVARCH 47754A13 DEVTYPE 13 ETM\n",
"[1][6]: E0003000 CID B105900D PID 000BBD22 DEVARCH 47700A06 DEVTYPE 16 ???\n",
"[1][7]: E0042000 CID B105900D PID 000BBD22 DEVARCH 47701A14 DEVTYPE 14 CSS600-CTI\n",
"[0][1]: E0040000 CID B105900D PID 000BBD22 DEVARCH 00000000 DEVTYPE 11 TPIU\n",
"[0][2]: E0045000 CID B105900D PID 006BB9E9 DEVARCH 00000000 DEVTYPE 21 ETB\n",
"I-Cache L1: 64 KB, 1024 Sets, 32 Bytes/Line, 2-Way\n",
"D-Cache L1: 64 KB, 512 Sets, 32 Bytes/Line, 4-Way\n",
"Memory zones:\n",
" Zone: \"Default\" Description: Default access mode\n",
"Cortex-M55 identified.\n",
"Reset delay: 0 ms\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 106ms\n",
"Device specific reset executed.\n",
"J-Link>LoadFile \n",
"/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/build/apoll\n",
"o510_evb/hpx_profiler.bin, 0x00410000\n",
"'loadfile': Performing implicit reset & halt of MCU.\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 104ms\n",
"Device specific reset executed.\n",
"Downloading file \n",
"[/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/build/apol\n",
"lo510_evb/hpx_profiler.bin]...\n",
"Erasing flash [000%]100%] Done.\n",
"Programming flash \n",
"[000%]000%]000%]000%]000%]000%]005%]005%]005%]005%]010%]010%]010%]010%]015%]015%]015%]015%]020%]020%]020%]020%]025%\n",
"]025%]025%]025%]025%]025%]030%]030%]030%]030%]035%]035%]035%]035%]040%]040%]040%]040%]045%]045%]045%]045%]050%]050%\n",
"]050%]050%]050%]050%]055%]055%]055%]055%]060%]060%]060%]060%]065%]065%]065%]065%]070%]070%]070%]070%]075%]075%]075%\n",
"]075%]075%]075%]080%]080%]080%]080%]085%]085%]085%]085%]090%]090%]090%]090%]095%]095%]095%]095%]100%] Done.\n",
"Verifying flash [000%]000%]035%]035%]070%]070%]100%] Done.\n",
"J-Link: Flash download: Bank 0 @ 0x00410000: 1 range affected (360448 bytes)\n",
"J-Link: Flash download: Total: 2.053s (Prepare: 0.138s, Compare: 0.000s, Erase: 0.000s, Program: 1.679s, Verify: \n",
"0.145s, Restore: 0.089s)\n",
"J-Link: Flash download: Program & Verify speed: 192 KB/s\n",
"O.K.\n",
"J-Link>Reset\n",
"Reset delay: 0 ms\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 106ms\n",
"Device specific reset executed.\n",
"J-Link>Go\n",
"Memory map 'after startup completion point' is active\n",
"J-Link>Exit\n",
"\n",
"Script processing completed.\n",
"\n",
"\n"
],
"text/plain": [
"[0/2] Re-checking globbed directories...\n",
"[1/2] Flashing hpx_profiler with SEGGER J-Link\n",
"SEGGER J-Link Commander V9.54 (Compiled Jun 25 2026 17:33:57)\n",
"DLL version V9.54, compiled Jun 25 2026 17:33:05\n",
"\n",
"\n",
"J-Link Command File read successfully.\n",
"Processing script file...\n",
"J-Link>ExitOnError 1\n",
"J-Link Commander will now exit on Error\n",
"J-Link>Reset\n",
"J-Link connection not established yet but required for command.\n",
"Connecting to J-Link ...O.K.\n",
"Firmware: J-Link OB-Apollo4-CortexM compiled Feb 5 2026 13:07:52\n",
"Hardware version: V1.00\n",
"J-Link uptime (since boot): 0d 02h 49m 36s\n",
"S/N: 1160002954\n",
"USB speed mode: Full speed (12 MBit/s)\n",
"VTref=1.800V\n",
"Target connection not established yet but required for command.\n",
"Device \"AP510NFA-CBR\" selected.\n",
"\n",
"\n",
"Connecting to target via SWD\n",
"ConfigTargetSettings() start\n",
"Disabling flash programming optimizations: SkipBlankDataOnProg\n",
"ConfigTargetSettings() end - Took 13us\n",
"Found SW-DP with ID 0x4C013477\n",
"DPIDR: 0x4C013477\n",
"CoreSight SoC-600 or later (DPv3 detected)\n",
"Detecting available APs\n",
"APSpace base (BASEPTR0): 0x00000000\n",
"APSpace size (DPIDR1.ASIZE): 12-bit (4 KB)\n",
"AP[0]: Stopped AP scan as end of AP map has been reached\n",
"AP[0] (APAddr 0x00000000): AHB-AP (IDR: 0x34770008)\n",
"Iterating through AP map to find AHB-AP to use\n",
"AP[0]: Core found\n",
"AP[0]: AHB-AP ROM base: 0xE00FE000\n",
"CPUID register: 0x411FD221. Implementer code: 0x41 (ARM)\n",
"Feature set: Mainline\n",
"Cache: L1 I/D-cache present\n",
"Found Cortex-M55 r1p1, Little endian.\n",
"FPUnit: 8 code (BP) slots and 0 literal slots\n",
"Security extension: implemented\n",
"Secure debug: enabled\n",
"PACBTI extension: not implemented\n",
"CoreSight components:\n",
"ROMTbl[0] @ E00FE000\n",
"[0][0]: E00FF000 CID B105100D PID 000BB4D2 DEVARCH 00000000 DEVTYPE 01 ROM Table\n",
"ROMTbl[1] @ E00FF000\n",
"[1][0]: E000E000 CID B105900D PID 000BBD22 DEVARCH 47702A04 DEVTYPE 00 ???\n",
"[1][1]: E0001000 CID B105900D PID 000BBD22 DEVARCH 47711A02 DEVTYPE 00 DWT\n",
"[1][2]: E0002000 CID B105900D PID 000BBD22 DEVARCH 47701A03 DEVTYPE 00 FPB\n",
"[1][3]: E0000000 CID B105900D PID 000BBD22 DEVARCH 47701A01 DEVTYPE 43 ITM\n",
"[1][5]: E0041000 CID B105900D PID 004BBD22 DEVARCH 47754A13 DEVTYPE 13 ETM\n",
"[1][6]: E0003000 CID B105900D PID 000BBD22 DEVARCH 47700A06 DEVTYPE 16 ???\n",
"[1][7]: E0042000 CID B105900D PID 000BBD22 DEVARCH 47701A14 DEVTYPE 14 CSS600-CTI\n",
"[0][1]: E0040000 CID B105900D PID 000BBD22 DEVARCH 00000000 DEVTYPE 11 TPIU\n",
"[0][2]: E0045000 CID B105900D PID 006BB9E9 DEVARCH 00000000 DEVTYPE 21 ETB\n",
"I-Cache L1: 64 KB, 1024 Sets, 32 Bytes/Line, 2-Way\n",
"D-Cache L1: 64 KB, 512 Sets, 32 Bytes/Line, 4-Way\n",
"Memory zones:\n",
" Zone: \"Default\" Description: Default access mode\n",
"Cortex-M55 identified.\n",
"Reset delay: 0 ms\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 106ms\n",
"Device specific reset executed.\n",
"J-Link>LoadFile \n",
"/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/build/apoll\n",
"o510_evb/hpx_profiler.bin, 0x00410000\n",
"'loadfile': Performing implicit reset & halt of MCU.\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 104ms\n",
"Device specific reset executed.\n",
"Downloading file \n",
"[/Users/adam.page/.cache/helia-profiler/workspaces/apollo510_evb-arm-none-eabi-gcc-helia-rt/profiler_app/build/apol\n",
"lo510_evb/hpx_profiler.bin]...\n",
"Erasing flash [000%]100%] Done.\n",
"Programming flash \n",
"[000%]000%]000%]000%]000%]000%]005%]005%]005%]005%]010%]010%]010%]010%]015%]015%]015%]015%]020%]020%]020%]020%]025%\n",
"]025%]025%]025%]025%]025%]030%]030%]030%]030%]035%]035%]035%]035%]040%]040%]040%]040%]045%]045%]045%]045%]050%]050%\n",
"]050%]050%]050%]050%]055%]055%]055%]055%]060%]060%]060%]060%]065%]065%]065%]065%]070%]070%]070%]070%]075%]075%]075%\n",
"]075%]075%]075%]080%]080%]080%]080%]085%]085%]085%]085%]090%]090%]090%]090%]095%]095%]095%]095%]100%] Done.\n",
"Verifying flash [000%]000%]035%]035%]070%]070%]100%] Done.\n",
"J-Link: Flash download: Bank 0 @ 0x00410000: 1 range affected (360448 bytes)\n",
"J-Link: Flash download: Total: 2.053s (Prepare: 0.138s, Compare: 0.000s, Erase: 0.000s, Program: 1.679s, Verify: \n",
"0.145s, Restore: 0.089s)\n",
"J-Link: Flash download: Program & Verify speed: 192 KB/s\n",
"O.K.\n",
"J-Link>Reset\n",
"Reset delay: 0 ms\n",
"ResetTarget() start\n",
"JDEC PID 0x00000EA0\n",
"Ambiq Apollo5 ResetTarget\n",
"Bootldr = 0xA4000005\n",
"Secure Part.\n",
"Secure Chip. Bootloader needs to run which will then halt when finish.\n",
"CPU halted after reset. TryCount = 0x00000000\n",
"ResetTarget() end - Took 106ms\n",
"Device specific reset executed.\n",
"J-Link>Go\n",
"Memory map 'after startup completion point' is active\n",
"J-Link>Exit\n",
"\n",
"Script processing completed.\n",
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n"
],
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"━━━━━━━━━━━━━━━━━━━━ 100% Done\n", "\n" ], "text/plain": [ " \u001b[36m━━━━━━━━━━━━━━━━━━━━\u001b[0m 100% \u001b[32mDone\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"───────────────────────────────────────────────────── Results ─────────────────────────────────────────────────────\n", "\n" ], "text/plain": [ "\u001b[94m───────────────────────────────────────────────────── \u001b[0m\u001b[1mResults\u001b[0m\u001b[94m ─────────────────────────────────────────────────────\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Engine helia-rt \n", " Board apollo510_evb \n", " Layers 6 \n", " Total cycles 39,341 \n", " Clean E2E cycles 36,864 (-6.3% vs per-layer sum) \n", " Total MACs 2,688 \n", " Total OPS 5,652 \n", " Cycles/MAC 14.64 \n", " Parameters 251 \n", "\n" ], "text/plain": [ "\u001b[2m \u001b[0m\u001b[2mEngine \u001b[0m\u001b[2m \u001b[0m \u001b[1mhelia-rt\u001b[0m \n", "\u001b[2m \u001b[0m\u001b[2mBoard \u001b[0m\u001b[2m \u001b[0m apollo510_evb \n", "\u001b[2m \u001b[0m\u001b[2mLayers \u001b[0m\u001b[2m \u001b[0m 6 \n", "\u001b[2m \u001b[0m\u001b[2mTotal cycles \u001b[0m\u001b[2m \u001b[0m \u001b[1;36m39,341\u001b[0m \n", "\u001b[2m \u001b[0m\u001b[2mClean E2E cycles\u001b[0m\u001b[2m \u001b[0m \u001b[1;32m36,864\u001b[0m \u001b[2m(-6.3% vs per-layer sum)\u001b[0m \n", "\u001b[2m \u001b[0m\u001b[2mTotal MACs \u001b[0m\u001b[2m \u001b[0m 2,688 \n", "\u001b[2m \u001b[0m\u001b[2mTotal OPS \u001b[0m\u001b[2m \u001b[0m 5,652 \n", "\u001b[2m \u001b[0m\u001b[2mCycles/MAC \u001b[0m\u001b[2m \u001b[0m 14.64 \n", "\u001b[2m \u001b[0m\u001b[2mParameters \u001b[0m\u001b[2m \u001b[0m 251 \n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Top Layers by Cycles \n", " # Operator Cycles % MACs Cyc/MAC \n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", " 1 CONV_2D 28,688 72.9% 2,304 12.5 \n", " 2 AVERAGE_POOL_2D 6,806 17.3% — — \n", " 3 CONV_2D 1,652 4.2% 192 8.6 \n", " 4 SOFTMAX 1,107 2.8% — — \n", " 5 FULLY_CONNECTED 769 2.0% 192 4.0 \n", "\n" ], "text/plain": [ "\u001b[1;3mTop Layers by Cycles\u001b[0m\u001b[3m \u001b[0m\n", "\u001b[1m \u001b[0m\u001b[1m #\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mOperator \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Cycles\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m %\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m MACs\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Cyc/MAC\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m\n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", "\u001b[2m \u001b[0m\u001b[2m 1\u001b[0m\u001b[2m \u001b[0m CONV_2D 28,688 \u001b[1;31m72.9%\u001b[0m 2,304 12.5 \n", "\u001b[2m \u001b[0m\u001b[2m 2\u001b[0m\u001b[2m \u001b[0m AVERAGE_POOL_2D 6,806 \u001b[33m17.3%\u001b[0m — — \n", "\u001b[2m \u001b[0m\u001b[2m 3\u001b[0m\u001b[2m \u001b[0m CONV_2D 1,652 \u001b[2m4.2%\u001b[0m 192 8.6 \n", "\u001b[2m \u001b[0m\u001b[2m 4\u001b[0m\u001b[2m \u001b[0m SOFTMAX 1,107 \u001b[2m2.8%\u001b[0m — — \n", "\u001b[2m \u001b[0m\u001b[2m 5\u001b[0m\u001b[2m \u001b[0m FULLY_CONNECTED 769 \u001b[2m2.0%\u001b[0m 192 4.0 \n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"╭─ Memory ──────────────────────────────────────────────────────╮\n", "│ │\n", "│ Arena 1,604 / 131,072 bytes ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 1% │\n", "│ Model 2,480 bytes │\n", "│ │\n", "│ Binary Sections │\n", "│ │\n", "╰───────────────────────────────────────────────────────────────╯\n", "\n" ], "text/plain": [ "\u001b[2m╭─\u001b[0m\u001b[2m \u001b[0m\u001b[1;2mMemory\u001b[0m\u001b[2m \u001b[0m\u001b[2m─────────────────────────────────────────────────────\u001b[0m\u001b[2m─╮\u001b[0m\n", "\u001b[2m│\u001b[0m \u001b[2m│\u001b[0m\n", "\u001b[2m│\u001b[0m Arena 1,604 / 131,072 bytes \u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 1% \u001b[2m│\u001b[0m\n", "\u001b[2m│\u001b[0m Model 2,480 bytes \u001b[2m│\u001b[0m\n", "\u001b[2m│\u001b[0m \u001b[2m│\u001b[0m\n", "\u001b[2m│\u001b[0m \u001b[1mBinary Sections\u001b[0m \u001b[2m│\u001b[0m\n", "\u001b[2m│\u001b[0m \u001b[2m│\u001b[0m\n", "\u001b[2m╰───────────────────────────────────────────────────────────────╯\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Section Size \n", " text 252,388 \n", " data 103,544 \n", " bss 502,912 \n", " total 858,844 \n", "\n" ], "text/plain": [ "\u001b[1m \u001b[0m\u001b[1mSection\u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m\u001b[1m Size\u001b[0m\u001b[1m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mtext \u001b[0m\u001b[2m \u001b[0m 252,388 \n", "\u001b[2m \u001b[0m\u001b[2mdata \u001b[0m\u001b[2m \u001b[0m 103,544 \n", "\u001b[2m \u001b[0m\u001b[2mbss \u001b[0m\u001b[2m \u001b[0m 502,912 \n", "\u001b[2m \u001b[0m\u001b[1;2mtotal\u001b[0m\u001b[2m \u001b[0m\u001b[2m \u001b[0m \u001b[1m858,844\u001b[0m \n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Memory Plan (helia-rt) \n", " Region Used Capacity % Consumers \n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", " MRAM 0 B 4.00 MB ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 0% — \n", " SRAM 0 B 3.00 MB ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 0% — \n", " DTCM 130.4 KB 512.0 KB ━━━━━╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 25% model_flatbuffer=2.4 KB, tensor_arena=128.0 \n", " KB \n", " ITCM 0 B 256.0 KB ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 0% — \n", " PSRAM 0 B 64.00 MB ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ 0% — \n", "\n" ], "text/plain": [ "\u001b[1;3mMemory Plan\u001b[0m\u001b[3m \u001b[0m\u001b[2;3m(helia-rt)\u001b[0m\u001b[3m \u001b[0m\n", "\u001b[1m \u001b[0m\u001b[1mRegion\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Used\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Capacity\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m %\u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1mConsumers \u001b[0m\u001b[1m \u001b[0m\n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", "\u001b[2m \u001b[0m\u001b[2mMRAM \u001b[0m\u001b[2m \u001b[0m 0 B 4.00 MB \u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 0% \u001b[2m \u001b[0m\u001b[2m— \u001b[0m\u001b[2m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mSRAM \u001b[0m\u001b[2m \u001b[0m 0 B 3.00 MB \u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 0% \u001b[2m \u001b[0m\u001b[2m— \u001b[0m\u001b[2m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mDTCM \u001b[0m\u001b[2m \u001b[0m 130.4 KB 512.0 KB \u001b[36m━━━━━\u001b[0m\u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 25% \u001b[2m \u001b[0m\u001b[2mmodel_flatbuffer=2.4 KB, tensor_arena=128.0 \u001b[0m\u001b[2m \u001b[0m\n", "\u001b[2m \u001b[0m \u001b[2m \u001b[0m\u001b[2mKB \u001b[0m\u001b[2m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mITCM \u001b[0m\u001b[2m \u001b[0m 0 B 256.0 KB \u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 0% \u001b[2m \u001b[0m\u001b[2m— \u001b[0m\u001b[2m \u001b[0m\n", "\u001b[2m \u001b[0m\u001b[2mPSRAM \u001b[0m\u001b[2m \u001b[0m 0 B 64.00 MB \u001b[2m╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌\u001b[0m 0% \u001b[2m \u001b[0m\u001b[2m— \u001b[0m\u001b[2m \u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Cache & Memory \n", " Counter Total \n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", " L1D_CACHE_REFILL 0 \n", " MEM_ACCESS 14,686 \n", " BUS_ACCESS 8 \n", "\n" ], "text/plain": [ "\u001b[1;3mCache & Memory\u001b[0m\u001b[3m \u001b[0m\n", "\u001b[1m \u001b[0m\u001b[1mCounter \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Total\u001b[0m\u001b[1m \u001b[0m\n", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n", " L1D_CACHE_REFILL 0 \n", " MEM_ACCESS 14,686 \n", " BUS_ACCESS 8 \n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n",
"\n"
],
"text/plain": [
"\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"╭─ Output → /Users/adam.page/Ambiq/helia/helia-profiler/examples/notebooks/results/notebook_showcase/helia_rt ─╮\n", "│ profile_results.csv │\n", "│ summary.json │\n", "│ run_metadata.json │\n", "│ model_explorer/me_overlay_ARM_PMU_CPU_CYCLES.json │\n", "│ model_explorer/me_overlay_ARM_PMU_INST_RETIRED.json │\n", "│ model_explorer/me_overlay_ARM_PMU_STALL_FRONTEND.json │\n", "│ model_explorer/me_overlay_ARM_PMU_STALL_BACKEND.json │\n", "│ model_explorer/me_overlay_ARM_PMU_MEM_ACCESS.json │\n", "│ model_explorer/me_overlay_ARM_PMU_L1D_CACHE_REFILL.json │\n", "│ model_explorer/me_overlay_ARM_PMU_BUS_ACCESS.json │\n", "│ model_explorer/me_overlay_ARM_PMU_BUS_CYCLES.json │\n", "│ detailed/profile_cpu_0.csv │\n", "│ detailed/profile_memory_0.csv │\n", "│ detailed/profile_cpu.csv │\n", "│ detailed/profile_memory.csv │\n", "│ detailed/memory.json │\n", "│ │\n", "╰──────────────────────────────────────────────────────────────────────────────────────────────── 85.3s total ─╯\n", "\n" ], "text/plain": [ "\u001b[94m╭─\u001b[0m\u001b[94m \u001b[0m\u001b[1;94mOutput → \u001b[0m\u001b]8;id=9427901;file:///Users/adam.page/Ambiq/helia/helia-profiler/examples/notebooks/results/notebook_showcase/helia_rt\u001b\\\u001b[1;94m/Users/adam.page/Ambiq/helia/helia-profiler/examples/notebooks/results/notebook_showcase/helia_rt\u001b[0m\u001b]8;;\u001b\\\u001b[94m \u001b[0m\u001b[94m─╮\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m profile_results.csv\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m summary.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m run_metadata.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_CPU_CYCLES.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_INST_RETIRED.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_STALL_FRONTEND.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_STALL_BACKEND.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_MEM_ACCESS.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_L1D_CACHE_REFILL.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_BUS_ACCESS.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m model_explorer/me_overlay_ARM_PMU_BUS_CYCLES.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m detailed/profile_cpu_0.csv\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m detailed/profile_memory_0.csv\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m detailed/profile_cpu.csv\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m detailed/profile_memory.csv\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[2m detailed/memory.json\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m│\u001b[0m \u001b[94m│\u001b[0m\n", "\u001b[94m╰─\u001b[0m\u001b[94m───────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m\u001b[94m \u001b[0m\u001b[2;94m85.3s total\u001b[0m\u001b[94m \u001b[0m\u001b[94m─╯\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Loaded 6 layers, 39,341 total cycles\n" ] } ], "source": [ "readiness = rt_session.show(rt_session.doctor())\n", "rt_result = None\n", "\n", "if RUN_HARDWARE and not readiness.ok:\n", " raise RuntimeError(\"Resolve the required environment checks before profiling\")\n", "\n", "if RUN_HARDWARE:\n", " rt_result = rt_session.profile()\n", " print(\n", " f\"Loaded {rt_result.layer_count} layers, \"\n", " f\"{rt_result.total_cycles:,.0f} total cycles\"\n", " )\n", "else:\n", " print(\"Profile acquisition skipped. Set RUN_HARDWARE = True to build and flash.\")" ] }, { "cell_type": "markdown", "id": "e8926bfd", "metadata": {}, "source": [ "## 3. Inspect Profile Metadata and Available Metrics\n", "\n", "Start with host readiness and discover the supported engines, boards, PMU groups, counters, and serial transports. Probe access is separately guarded because discovery communicates with SEGGER tools." ] }, { "cell_type": "code", "execution_count": 4, "id": "289b0359", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Inference \n", "Engines \n", "╭───────────╮\n", "│ Engine │\n", "├───────────┤\n", "│ tflm │\n", "│ helia-rt │\n", "│ helia-aot │\n", "╰───────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mInference \u001b[0m\u001b[3m \u001b[0m\n", "\u001b[1;3mEngines\u001b[0m\u001b[3m \u001b[0m\n", "╭───────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mEngine \u001b[0m\u001b[1m \u001b[0m│\n", "├───────────┤\n", "│ tflm │\n", "│ helia-rt │\n", "│ helia-aot │\n", "╰───────────╯\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Boards \n", "╭────────────────────────┬──────────────┬─────────╮\n", "│ Board │ SoC │ Channel │\n", "├────────────────────────┼──────────────┼─────────┤\n", "│ apollo3p_evb │ apollo3p │ stable │\n", "│ apollo3p_evb_cygnus │ apollo3p │ preview │\n", "│ apollo4p_evb │ apollo4p │ preview │\n", "│ apollo4l_evb │ apollo4l │ preview │\n", "│ apollo4l_blue_evb │ apollo4l │ preview │\n", "│ apollo4p_blue_kbr_evb │ apollo4p │ preview │\n", "│ apollo4p_blue_kxr_evb │ apollo4p │ preview │\n", "│ apollo510_evb │ apollo510 │ stable │\n", "│ apollo510b_evb │ apollo510b │ preview │\n", "│ apollo5b_evb │ apollo5b │ preview │\n", "│ apollo330mP_evb │ apollo330P │ preview │\n", "╰────────────────────────┴──────────────┴─────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mBoards\u001b[0m\u001b[3m \u001b[0m\n", "╭────────────────────────┬──────────────┬─────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mBoard \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mSoC \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mChannel\u001b[0m\u001b[1m \u001b[0m│\n", "├────────────────────────┼──────────────┼─────────┤\n", "│ apollo3p_evb │ apollo3p │ stable │\n", "│ apollo3p_evb_cygnus │ apollo3p │ preview │\n", "│ apollo4p_evb │ apollo4p │ preview │\n", "│ apollo4l_evb │ apollo4l │ preview │\n", "│ apollo4l_blue_evb │ apollo4l │ preview │\n", "│ apollo4p_blue_kbr_evb │ apollo4p │ preview │\n", "│ apollo4p_blue_kxr_evb │ apollo4p │ preview │\n", "│ apollo510_evb │ apollo510 │ stable │\n", "│ apollo510b_evb │ apollo510b │ preview │\n", "│ apollo5b_evb │ apollo5b │ preview │\n", "│ apollo330mP_evb │ apollo330P │ preview │\n", "╰────────────────────────┴──────────────┴─────────╯\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Serial Ports \n", "╭───────────────────────────────┬────────────┬──────────────┬─────────────╮\n", "│ Device │ Kind │ Serial │ Description │\n", "├───────────────────────────────┼────────────┼──────────────┼─────────────┤\n", "│ /dev/cu.usbmodem0011600029541 │ jlink-vcom │ 001160002954 │ J-Link │\n", "╰───────────────────────────────┴────────────┴──────────────┴─────────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mSerial Ports\u001b[0m\u001b[3m \u001b[0m\n", "╭───────────────────────────────┬────────────┬──────────────┬─────────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mDevice \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mKind \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mSerial \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mDescription\u001b[0m\u001b[1m \u001b[0m│\n", "├───────────────────────────────┼────────────┼──────────────┼─────────────┤\n", "│ /dev/cu.usbmodem0011600029541 │ jlink-vcom │ 001160002954 │ J-Link │\n", "╰───────────────────────────────┴────────────┴──────────────┴─────────────╯\n" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "Counter groups: cpu, memory, mve\n" ] }, { "data": { "text/html": [ "
PMU Counters \n", "╭────────────────────────────────┬───────┬───────┬────────────────────────────────────────────────────────────────╮\n", "│ Counter │ Group │ Event │ Description │\n", "├────────────────────────────────┼───────┼───────┼────────────────────────────────────────────────────────────────┤\n", "│ ARM_PMU_SW_INCR │ cpu │ 0x00 │ Software update to the PMU_SWINC register, architecturally │\n", "│ │ │ │ executed and condition code check pass │\n", "│ ARM_PMU_L1I_CACHE_REFILL │ cpu │ 0x01 │ L1 I-Cache refill │\n", "│ ARM_PMU_LD_RETIRED │ cpu │ 0x06 │ Memory-reading instruction architecturally executed and │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_ST_RETIRED │ cpu │ 0x07 │ Memory-writing instruction architecturally executed and │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_INST_RETIRED │ cpu │ 0x08 │ Instruction architecturally executed │\n", "│ ARM_PMU_EXC_TAKEN │ cpu │ 0x09 │ Exception entry │\n", "│ ARM_PMU_EXC_RETURN │ cpu │ 0x0a │ Exception return instruction architecturally executed and the │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_PC_WRITE_RETIRED │ cpu │ 0x0c │ Software change to the Program Counter (PC). Instruction is │\n", "│ │ │ │ architecturally executed and condition code check pass │\n", "│ ARM_PMU_BR_IMMED_RETIRED │ cpu │ 0x0d │ Immediate branch architecturally executed │\n", "│ ARM_PMU_BR_RETURN_RETIRED │ cpu │ 0x0e │ Function return instruction architecturally executed and the │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_UNALIGNED_LDST_RETIRED │ cpu │ 0x0f │ Unaligned memory memory-reading or memory-writing instruction │\n", "│ │ │ │ architecturally executed and condition code check pass │\n", "│ ARM_PMU_CPU_CYCLES │ cpu │ 0x11 │ Cycle │\n", "│ ARM_PMU_BR_RETIRED │ cpu │ 0x21 │ Branch instruction architecturally executed │\n", "│ ARM_PMU_BR_MIS_PRED_RETIRED │ cpu │ 0x22 │ Mispredicted branch instruction architecturally executed │\n", "│ ARM_PMU_STALL_FRONTEND │ cpu │ 0x23 │ No operation issued because of the frontend │\n", "│ ARM_PMU_STALL_BACKEND │ cpu │ 0x24 │ No operation issued because of the backend │\n", "│ ARM_PMU_STALL │ cpu │ 0x3c │ Stall cycle for instruction or operation not sent for │\n", "│ │ │ │ execution │\n", "│ ARM_PMU_LE_RETIRED │ cpu │ 0x100 │ Loop end instruction executed │\n", "│ ARM_PMU_LE_CANCEL │ cpu │ 0x108 │ Loop end instruction not taken │\n", "│ ARM_PMU_SE_CALL_S │ cpu │ 0x114 │ Call to secure function, resulting in Security state change │\n", "│ ARM_PMU_SE_CALL_NS │ cpu │ 0x115 │ Call to non-secure function, resulting in Security state │\n", "│ │ │ │ change │\n", "╰────────────────────────────────┴───────┴───────┴────────────────────────────────────────────────────────────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mPMU Counters\u001b[0m\u001b[3m \u001b[0m\n", "╭────────────────────────────────┬───────┬───────┬────────────────────────────────────────────────────────────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mCounter \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mGroup\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mEvent\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mDescription \u001b[0m\u001b[1m \u001b[0m│\n", "├────────────────────────────────┼───────┼───────┼────────────────────────────────────────────────────────────────┤\n", "│ ARM_PMU_SW_INCR │ cpu │ 0x00 │ Software update to the PMU_SWINC register, architecturally │\n", "│ │ │ │ executed and condition code check pass │\n", "│ ARM_PMU_L1I_CACHE_REFILL │ cpu │ 0x01 │ L1 I-Cache refill │\n", "│ ARM_PMU_LD_RETIRED │ cpu │ 0x06 │ Memory-reading instruction architecturally executed and │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_ST_RETIRED │ cpu │ 0x07 │ Memory-writing instruction architecturally executed and │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_INST_RETIRED │ cpu │ 0x08 │ Instruction architecturally executed │\n", "│ ARM_PMU_EXC_TAKEN │ cpu │ 0x09 │ Exception entry │\n", "│ ARM_PMU_EXC_RETURN │ cpu │ 0x0a │ Exception return instruction architecturally executed and the │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_PC_WRITE_RETIRED │ cpu │ 0x0c │ Software change to the Program Counter (PC). Instruction is │\n", "│ │ │ │ architecturally executed and condition code check pass │\n", "│ ARM_PMU_BR_IMMED_RETIRED │ cpu │ 0x0d │ Immediate branch architecturally executed │\n", "│ ARM_PMU_BR_RETURN_RETIRED │ cpu │ 0x0e │ Function return instruction architecturally executed and the │\n", "│ │ │ │ condition code check pass │\n", "│ ARM_PMU_UNALIGNED_LDST_RETIRED │ cpu │ 0x0f │ Unaligned memory memory-reading or memory-writing instruction │\n", "│ │ │ │ architecturally executed and condition code check pass │\n", "│ ARM_PMU_CPU_CYCLES │ cpu │ 0x11 │ Cycle │\n", "│ ARM_PMU_BR_RETIRED │ cpu │ 0x21 │ Branch instruction architecturally executed │\n", "│ ARM_PMU_BR_MIS_PRED_RETIRED │ cpu │ 0x22 │ Mispredicted branch instruction architecturally executed │\n", "│ ARM_PMU_STALL_FRONTEND │ cpu │ 0x23 │ No operation issued because of the frontend │\n", "│ ARM_PMU_STALL_BACKEND │ cpu │ 0x24 │ No operation issued because of the backend │\n", "│ ARM_PMU_STALL │ cpu │ 0x3c │ Stall cycle for instruction or operation not sent for │\n", "│ │ │ │ execution │\n", "│ ARM_PMU_LE_RETIRED │ cpu │ 0x100 │ Loop end instruction executed │\n", "│ ARM_PMU_LE_CANCEL │ cpu │ 0x108 │ Loop end instruction not taken │\n", "│ ARM_PMU_SE_CALL_S │ cpu │ 0x114 │ Call to secure function, resulting in Security state change │\n", "│ ARM_PMU_SE_CALL_NS │ cpu │ 0x115 │ Call to non-secure function, resulting in Security state │\n", "│ │ │ │ change │\n", "╰────────────────────────────────┴───────┴───────┴────────────────────────────────────────────────────────────────╯\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
J-Link Probes \n", "╭──────────────┬───────────────────────────┬────────────╮\n", "│ Serial │ Product │ Connection │\n", "├──────────────┼───────────────────────────┼────────────┤\n", "│ 1160002954 │ J-Link-OB-Apollo4-CortexM │ USB │\n", "╰──────────────┴───────────────────────────┴────────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mJ-Link Probes\u001b[0m\u001b[3m \u001b[0m\n", "╭──────────────┬───────────────────────────┬────────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mSerial \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mProduct \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mConnection\u001b[0m\u001b[1m \u001b[0m│\n", "├──────────────┼───────────────────────────┼────────────┤\n", "│ 1160002954 │ J-Link-OB-Apollo4-CortexM │ USB │\n", "╰──────────────┴───────────────────────────┴────────────╯\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
J-Link Probe Targets \n", "╭──────────────┬───────────────────────────┬───────────────╮\n", "│ Serial │ Product │ Detected Core │\n", "├──────────────┼───────────────────────────┼───────────────┤\n", "│ 1160002954 │ J-Link-OB-Apollo4-CortexM │ cortex-m55 │\n", "╰──────────────┴───────────────────────────┴───────────────╯\n", "\n" ], "text/plain": [ "\u001b[1;3mJ-Link Probe Targets\u001b[0m\u001b[3m \u001b[0m\n", "╭──────────────┬───────────────────────────┬───────────────╮\n", "│\u001b[1m \u001b[0m\u001b[1mSerial \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mProduct \u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mDetected Core\u001b[0m\u001b[1m \u001b[0m│\n", "├──────────────┼───────────────────────────┼───────────────┤\n", "│ 1160002954 │ J-Link-OB-Apollo4-CortexM │ cortex-m55 │\n", "╰──────────────┴───────────────────────────┴───────────────╯\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "doctor = readiness\n", "engines = base.show(base.engines())\n", "boards = base.show(base.boards())\n", "ports = base.show(base.ports())\n", "\n", "print(\"Counter groups:\", \", \".join(base.counter_groups()))\n", "cpu_counters = base.show(base.counters(\"cpu\"))\n", "\n", "probes = ()\n", "probe_matches = ()\n", "if RUN_PROBE_DISCOVERY:\n", " probes = base.show(base.probes())\n", " probe_matches = base.show(base.inspect_probes())\n", "else:\n", " print(\"Probe discovery skipped. Set RUN_PROBE_DISCOVERY = True to query J-Link.\")" ] }, { "cell_type": "code", "execution_count": null, "id": "87b81c53", "metadata": {}, "outputs": [], "source": [ "resolved = rt_session.resolve()\n", "config_table = Table(title=\"Resolved RT Experiment\")\n", "config_table.add_column(\"Setting\")\n", "config_table.add_column(\"Value\")\n", "config_table.add_row(\"Model\", str(resolved.model.path))\n", "config_table.add_row(\"Engine\", resolved.engine.type.value)\n", "config_table.add_row(\"Board\", resolved.target.board)\n", "config_table.add_row(\"Toolchain\", resolved.target.toolchain.value)\n", "config_table.add_row(\"Transport\", resolved.target.transport.value)\n", "config_table.add_row(\"Iterations\", str(resolved.profiling.iterations))\n", "config_table.add_row(\"Warmup\", str(resolved.profiling.warmup))\n", "config_table.add_row(\"PMU groups\", \", \".join((resolved.profiling.pmu_counters or {}).keys()))\n", "console.print(config_table)\n", "\n", "if rt_result is not None:\n", " print(\"Run ID:\", rt_result.metadata.run_id)\n", " print(\"Available PMU presets:\", sorted(rt_result.pmu.presets))\n", " print(\"Available compute groups:\", sorted(rt_result.pmu.groups))\n", " print(\"Firmware metadata:\", rt_result.pmu.meta)" ] }, { "cell_type": "markdown", "id": "b3ae3f13", "metadata": {}, "source": [ "## 4. Summarize Runtime and Layer Execution\n", "\n", "HPX measures model operators rather than host tasks. The equivalent headline view reports layer count, summed instrumented cycles, clean end-to-end latency, capture duration, overflow status, and operator diversity." ] }, { "cell_type": "code", "execution_count": null, "id": "dd9940f3", "metadata": {}, "outputs": [], "source": [ "summary_rows = []\n", "if rt_result is not None:\n", " firmware = rt_result.pmu.meta\n", " timing = rt_result.metadata.timing\n", " summary_rows = [\n", " (\"Layers\", rt_result.layer_count),\n", " (\"Operator types\", len({layer.op for layer in rt_result.layers})),\n", " (\"Instrumented layer cycles\", rt_result.total_cycles),\n", " (\"Clean inference cycles\", firmware.clean_infer_avg_cycles),\n", " (\"Clean inference time (us)\", firmware.clean_infer_avg_us),\n", " (\"Capture duration (s)\", timing.capture_duration_s if timing else None),\n", " (\"Counter overflow\", rt_result.overflow_detected),\n", " ]\n", "\n", "summary_table = Table(title=\"Profile Summary\")\n", "summary_table.add_column(\"Metric\")\n", "summary_table.add_column(\"Value\", justify=\"right\")\n", "for label, value in summary_rows:\n", " summary_table.add_row(label, \"-\" if value is None else f\"{value:,}\" if isinstance(value, (int, float)) else str(value))\n", "console.print(summary_table if summary_rows else \"[dim]No profile result loaded.[/dim]\")" ] }, { "cell_type": "markdown", "id": "a8d4ef96", "metadata": {}, "source": [ "## 5. Explore the HPX Layer and Memory Hierarchy\n", "\n", "TFLite operator results are a flat execution sequence, not a parent-child task trace. HPX adds two useful structures: operator-type aggregation across that sequence and a memory plan whose regions contain named consumers such as weights, arena, and code." ] }, { "cell_type": "code", "execution_count": null, "id": "5d6e1f83", "metadata": {}, "outputs": [], "source": [ "operator_summary = []\n", "if rt_result is not None:\n", " by_op = {}\n", " for layer in rt_result.layers:\n", " bucket = by_op.setdefault(layer.op, {\"count\": 0, \"cycles\": 0.0})\n", " bucket[\"count\"] += 1\n", " bucket[\"cycles\"] += layer.cycles or 0\n", " operator_summary = sorted(\n", " ({\"op\": op, **values} for op, values in by_op.items()),\n", " key=lambda row: row[\"cycles\"],\n", " reverse=True,\n", " )\n", "\n", "op_table = Table(title=\"Operator Hierarchy Summary\")\n", "op_table.add_column(\"Operator\")\n", "op_table.add_column(\"Layers\", justify=\"right\")\n", "op_table.add_column(\"Total cycles\", justify=\"right\")\n", "op_table.add_column(\"Share\", justify=\"right\")\n", "for row in operator_summary:\n", " share = row[\"cycles\"] / rt_result.total_cycles if rt_result and rt_result.total_cycles else 0\n", " op_table.add_row(row[\"op\"], str(row[\"count\"]), f\"{row['cycles']:,.0f}\", f\"{share:.1%}\")\n", "console.print(op_table if operator_summary else \"[dim]No operator data loaded.[/dim]\")\n", "\n", "memory_plan = rt_result.metadata.memory_plan if rt_result is not None else None\n", "if memory_plan is not None:\n", " for region in memory_plan.regions:\n", " print(f\"{region.region.value}: {region.used:,}/{region.capacity:,} bytes\")\n", " for consumer in region.consumers:\n", " print(f\" - {consumer.kind.value}: {consumer.name} ({consumer.size:,} bytes)\")\n", "else:\n", " print(\"No resolved memory plan is available until a profile completes.\")" ] }, { "cell_type": "markdown", "id": "ab132e24", "metadata": {}, "source": [ "## 6. Analyze Layer Timing Distributions\n", "\n", "Group layers by operator and compute count, total, mean, median, p90, and maximum cycles. This exposes both frequently executed operators and individual timing outliers without introducing a dataframe dependency." ] }, { "cell_type": "code", "execution_count": null, "id": "e68953d3", "metadata": {}, "outputs": [], "source": [ "def percentile(values, fraction):\n", " if not values:\n", " return 0.0\n", " ordered = sorted(values)\n", " index = min(len(ordered) - 1, round((len(ordered) - 1) * fraction))\n", " return ordered[index]\n", "\n", "\n", "timing_rows = []\n", "if rt_result is not None:\n", " grouped = {}\n", " for layer in rt_result.layers:\n", " grouped.setdefault(layer.op, []).append(float(layer.cycles or 0))\n", " for op, values in grouped.items():\n", " timing_rows.append(\n", " {\n", " \"op\": op,\n", " \"count\": len(values),\n", " \"total\": sum(values),\n", " \"mean\": mean(values),\n", " \"median\": median(values),\n", " \"p90\": percentile(values, 0.90),\n", " \"max\": max(values),\n", " }\n", " )\n", " timing_rows.sort(key=lambda row: row[\"total\"], reverse=True)\n", "\n", "timing_table = Table(title=\"Layer Timing Distribution\")\n", "for label in (\"Operator\", \"Count\", \"Total\", \"Mean\", \"Median\", \"P90\", \"Max\"):\n", " timing_table.add_column(label, justify=\"right\" if label != \"Operator\" else \"left\")\n", "for row in timing_rows:\n", " timing_table.add_row(\n", " row[\"op\"], str(row[\"count\"]),\n", " f\"{row['total']:,.0f}\", f\"{row['mean']:,.0f}\",\n", " f\"{row['median']:,.0f}\", f\"{row['p90']:,.0f}\", f\"{row['max']:,.0f}\",\n", " )\n", "console.print(timing_table if timing_rows else \"[dim]No layer timings loaded.[/dim]\")" ] }, { "cell_type": "markdown", "id": "0abcb111", "metadata": {}, "source": [ "## 7. Visualize Execution Across Compute-Unit Lanes\n", "\n", "HPX profiles one embedded inference core per run, so it does not expose host worker threads. Its closest lane view is the set of PMU compute groups (`cpu`, `memory`, `mve`) merged across firmware passes. The table below ranks layers within each available lane and supports a layer-index zoom." ] }, { "cell_type": "code", "execution_count": null, "id": "77842bb5", "metadata": {}, "outputs": [], "source": [ "ZOOM_LAYER_RANGE = (0, 20)\n", "lane_table = Table(title=f\"Compute Lanes: layers {ZOOM_LAYER_RANGE[0]}..{ZOOM_LAYER_RANGE[1]}\")\n", "lane_table.add_column(\"Lane\")\n", "lane_table.add_column(\"Layer\")\n", "lane_table.add_column(\"Operator\")\n", "lane_table.add_column(\"Leading counter\")\n", "lane_table.add_column(\"Value\", justify=\"right\")\n", "\n", "if rt_result is not None:\n", " for group_name, layers in sorted(rt_result.pmu.groups.items()):\n", " for layer in layers[ZOOM_LAYER_RANGE[0]:ZOOM_LAYER_RANGE[1]]:\n", " leading = max(layer.counters, key=layer.counters.get) if layer.counters else \"cycles\"\n", " value = layer.counters.get(leading, layer.cycles or 0)\n", " lane_table.add_row(group_name, str(layer.id), layer.op, leading, f\"{value:,.0f}\")\n", "console.print(lane_table if lane_table.row_count else \"[dim]No compute-lane data loaded.[/dim]\")" ] }, { "cell_type": "markdown", "id": "83f0bd33", "metadata": {}, "source": [ "## 8. Identify Imbalances and Bottlenecks\n", "\n", "On a single inference core, imbalance means concentration rather than worker skew: a small number of layers consuming most cycles, high stall counters, memory-refill pressure, or a large gap between instrumented and clean inference timing. The following rankings report measured values; interpretation remains workload-specific." ] }, { "cell_type": "code", "execution_count": null, "id": "cef424cd", "metadata": {}, "outputs": [], "source": [ "hotspots = []\n", "if rt_result is not None:\n", " hotspots = sorted(rt_result.layers, key=lambda layer: layer.cycles or 0, reverse=True)\n", "\n", "hotspot_table = Table(title=\"Cycle Hotspots\")\n", "hotspot_table.add_column(\"Rank\", justify=\"right\")\n", "hotspot_table.add_column(\"Layer\")\n", "hotspot_table.add_column(\"Operator\")\n", "hotspot_table.add_column(\"Cycles\", justify=\"right\")\n", "hotspot_table.add_column(\"Profile share\", justify=\"right\")\n", "hotspot_table.add_column(\"Overflow\")\n", "for rank, layer in enumerate(hotspots[:12], 1):\n", " cycles = layer.cycles or 0\n", " share = cycles / rt_result.total_cycles if rt_result and rt_result.total_cycles else 0\n", " hotspot_table.add_row(\n", " str(rank), str(layer.id), layer.op, f\"{cycles:,.0f}\", f\"{share:.1%}\", str(layer.overflow)\n", " )\n", "console.print(hotspot_table if hotspots else \"[dim]No hotspot data loaded.[/dim]\")\n", "\n", "if hotspots and rt_result.total_cycles:\n", " top_share = sum((layer.cycles or 0) for layer in hotspots[:5]) / rt_result.total_cycles\n", " print(f\"Measured concentration: top five layers account for {top_share:.1%} of layer cycles.\")" ] }, { "cell_type": "markdown", "id": "80a4bb6d", "metadata": {}, "source": [ "## 9. Filter and Drill Down\n", "\n", "Compose filters by operator text, layer ID range, minimum cycle count, overflow state, and counter availability. The filtered list can feed the same summary and hotspot views without mutating the original `ProfileResult`." ] }, { "cell_type": "code", "execution_count": null, "id": "361a0b1d", "metadata": {}, "outputs": [], "source": [ "def filter_layers(\n", " layers,\n", " *,\n", " op_contains=None,\n", " id_range=None,\n", " min_cycles=0,\n", " overflow_only=False,\n", " counter=None,\n", "):\n", " selected = []\n", " for index, layer in enumerate(layers):\n", " numeric_id = layer.id if isinstance(layer.id, int) else index\n", " if op_contains and op_contains.lower() not in layer.op.lower():\n", " continue\n", " if id_range and not (id_range[0] <= numeric_id < id_range[1]):\n", " continue\n", " if (layer.cycles or 0) < min_cycles:\n", " continue\n", " if overflow_only and not layer.overflow:\n", " continue\n", " if counter and counter not in layer.counters:\n", " continue\n", " selected.append(layer)\n", " return selected\n", "\n", "\n", "cycle_floor = (rt_result.total_cycles * 0.01) if rt_result is not None else 0\n", "filtered_layers = filter_layers(\n", " rt_result.layers if rt_result is not None else [],\n", " id_range=(0, 30),\n", " min_cycles=cycle_floor,\n", " counter=\"ARM_PMU_CPU_CYCLES\",\n", ")\n", "\n", "filtered_table = Table(title=\"Filtered Layers\")\n", "filtered_table.add_column(\"Layer\")\n", "filtered_table.add_column(\"Operator\")\n", "filtered_table.add_column(\"Cycles\", justify=\"right\")\n", "for layer in sorted(filtered_layers, key=lambda item: item.cycles or 0, reverse=True):\n", " filtered_table.add_row(str(layer.id), layer.op, f\"{layer.cycles or 0:,.0f}\")\n", "console.print(filtered_table if filtered_layers else \"[dim]No layers match the current drill-down.[/dim]\")" ] }, { "cell_type": "markdown", "id": "bb2b1e5d", "metadata": {}, "source": [ "## 10. Correlate Layers with Model Provenance\n", "\n", "TFLite flatbuffers generally do not carry source file and line information. HPX instead preserves model name, size, SHA-256, layer/operator IDs, and—when AOT analysis is available—original operator IDs through graph transformations. Missing optional analysis support is reported without stopping the notebook." ] }, { "cell_type": "code", "execution_count": null, "id": "21e2c7df", "metadata": {}, "outputs": [], "source": [ "if rt_result is not None and rt_result.metadata.model is not None:\n", " model_info = rt_result.metadata.model\n", " print(\"Model:\", model_info.name)\n", " print(\"Size: \", f\"{model_info.size_bytes:,} bytes\")\n", " print(\"SHA: \", model_info.sha256)\n", "else:\n", " print(\"Runtime model provenance will be available after profiling.\")\n", "\n", "rt_analysis = None\n", "aot_analysis = None\n", "try:\n", " rt_analysis = rt_session.analyze()\n", " print(\n", " f\"RT graph: {len(rt_analysis.layers)} layers, \"\n", " f\"{rt_analysis.total_macs:,} MACs, {rt_analysis.total_ops:,} operations\"\n", " )\n", "except hpx.HpxError as exc:\n", " print(\"RT analysis unavailable:\", exc)\n", "\n", "try:\n", " aot_analysis = aot_session.analyze()\n", " mapped = sum(layer.original_id is not None for layer in aot_analysis.layers)\n", " print(\n", " f\"AOT graph: {len(aot_analysis.layers)} layers, \"\n", " f\"{mapped} layers mapped to original operator IDs\"\n", " )\n", "except hpx.HpxError as exc:\n", " print(\"AOT analysis unavailable:\", exc)" ] }, { "cell_type": "markdown", "id": "ea96716c", "metadata": {}, "source": [ "## 11. Compare Execution Regions and Engines\n", "\n", "First compare two layer windows from the RT run to quantify local concentration. Then, when hardware profiling is enabled, run the independently derived AOT session and use HPX's typed comparison API to compare complete RT and AOT result sets." ] }, { "cell_type": "code", "execution_count": null, "id": "997762d3", "metadata": {}, "outputs": [], "source": [ "def summarize_region(name, layers):\n", " cycles = [float(layer.cycles or 0) for layer in layers]\n", " return {\n", " \"region\": name,\n", " \"layers\": len(layers),\n", " \"total_cycles\": sum(cycles),\n", " \"mean_cycles\": mean(cycles) if cycles else 0,\n", " \"dominant_op\": max(\n", " {layer.op for layer in layers},\n", " key=lambda op: sum((layer.cycles or 0) for layer in layers if layer.op == op),\n", " ) if layers else \"-\",\n", " }\n", "\n", "region_rows = []\n", "if rt_result is not None:\n", " midpoint = len(rt_result.layers) // 2\n", " region_rows = [\n", " summarize_region(\"first half\", rt_result.layers[:midpoint]),\n", " summarize_region(\"second half\", rt_result.layers[midpoint:]),\n", " ]\n", "\n", "region_table = Table(title=\"Execution Region Comparison\")\n", "for label in (\"Region\", \"Layers\", \"Total cycles\", \"Mean cycles\", \"Dominant operator\"):\n", " region_table.add_column(label)\n", "for row in region_rows:\n", " region_table.add_row(\n", " row[\"region\"], str(row[\"layers\"]), f\"{row['total_cycles']:,.0f}\",\n", " f\"{row['mean_cycles']:,.0f}\", row[\"dominant_op\"],\n", " )\n", "if len(region_rows) == 2:\n", " delta = region_rows[1][\"total_cycles\"] - region_rows[0][\"total_cycles\"]\n", " region_table.caption = f\"Second - first total-cycle delta: {delta:+,.0f}\"\n", "console.print(region_table if region_rows else \"[dim]No execution regions loaded.[/dim]\")" ] }, { "cell_type": "code", "execution_count": null, "id": "86a4352e", "metadata": {}, "outputs": [], "source": [ "aot_result = None\n", "comparison = None\n", "if RUN_HARDWARE:\n", " try:\n", " aot_result = aot_session.profile()\n", " comparison = base.compare(\n", " rt_result,\n", " aot_result,\n", " output_dir=COMPARE_RESULTS,\n", " )\n", " print(f\"Compared {len(comparison.layer_rows)} aligned layers\")\n", " for metric in comparison.metrics:\n", " if metric.delta is not None:\n", " print(\n", " f\"{metric.name}: {metric.baseline} -> {metric.candidate} \"\n", " f\"(delta {metric.delta:+g})\"\n", " )\n", " except hpx.HpxError as exc:\n", " print(\"AOT profile or comparison unavailable:\", exc)\n", "else:\n", " print(\"RT-vs-AOT hardware comparison skipped.\")" ] }, { "cell_type": "markdown", "id": "e9f8e447", "metadata": {}, "source": [ "## Configuration Snapshots, Overlays, and Optional Power\n", "\n", "`Session.from_yaml()` snapshots configuration at construction, so later file edits cannot change an existing experiment. Model Explorer overlays remain ordinary report paths.\n", "\n", "Joulescope power capture is a separate opt-in branch. `RUN_HARDWARE` controls ordinary RT/AOT profiling; `RUN_POWER` independently controls the power-enabled run. Leave `RUN_POWER = False` when no Joulescope is connected." ] }, { "cell_type": "code", "execution_count": null, "id": "cac9020e", "metadata": {}, "outputs": [], "source": [ "with tempfile.TemporaryDirectory(prefix=\"hpx_session_\") as temp_dir:\n", " config_path = Path(temp_dir) / \"profile.yml\"\n", " config_path.write_text(\n", " f\"model:\\n path: {MODEL}\\ntarget:\\n board: {BOARD}\\n\"\n", " )\n", " yaml_session = hpx.Session.from_yaml(config_path)\n", " config_path.write_text(\"model:\\n path: changed-after-snapshot.tflite\\n\")\n", " assert yaml_session.resolve().model.path == MODEL\n", " print(\"YAML snapshot model:\", yaml_session.resolve().model.path)\n", "\n", "power_session = (\n", " rt_session\n", " .with_power(enabled=True, duration_s=10)\n", " .with_output(dir=RESULTS_ROOT / \"power\")\n", ")\n", "print(\"Power enabled in branch:\", power_session.resolve().power.enabled)\n", "print(\"Power duration: \", power_session.resolve().power.duration_s)\n", "\n", "power_result = None\n", "if RUN_POWER:\n", " if not RUN_HARDWARE:\n", " raise RuntimeError(\"Set RUN_HARDWARE = True before enabling RUN_POWER\")\n", " power_result = power_session.profile()\n", "else:\n", " print(\"Power capture skipped. Set RUN_POWER = True only with a Joulescope connected.\")\n", "\n", "overlay_paths = [\n", " path\n", " for result in (rt_result, aot_result)\n", " if result is not None\n", " for path in result.report_paths\n", " if path.name.startswith(\"me_overlay_\")\n", "]\n", "print(\"Model Explorer overlays:\", len(overlay_paths))\n", "for path in overlay_paths[:8]:\n", " print(\" \", path)" ] }, { "cell_type": "markdown", "id": "0af4ed4c", "metadata": {}, "source": [ "## 12. Export Analysis Results and Visualizations\n", "\n", "Write derived tables beneath the repository-ignored `results/` tree, never into fixtures. CSV and JSON retain machine-readable analysis; a captured Rich hotspot table provides a portable text visualization. HPX's own reports and Model Explorer overlays remain in each run directory." ] }, { "cell_type": "code", "execution_count": null, "id": "efdba53a", "metadata": {}, "outputs": [], "source": [ "EXPORT_DIR.mkdir(parents=True, exist_ok=True)\n", "summary_csv = EXPORT_DIR / \"operator_timing_summary.csv\"\n", "summary_json = EXPORT_DIR / \"showcase_summary.json\"\n", "hotspot_text = EXPORT_DIR / \"cycle_hotspots.txt\"\n", "\n", "fieldnames = [\"op\", \"count\", \"total\", \"mean\", \"median\", \"p90\", \"max\"]\n", "with summary_csv.open(\"w\", newline=\"\") as stream:\n", " writer = csv.DictWriter(stream, fieldnames=fieldnames)\n", " writer.writeheader()\n", " writer.writerows(timing_rows)\n", "\n", "summary_json.write_text(\n", " json.dumps(\n", " {\n", " \"hpx_version\": hpx.__version__,\n", " \"model\": str(MODEL),\n", " \"board\": BOARD,\n", " \"profile_loaded\": rt_result is not None,\n", " \"layers\": rt_result.layer_count if rt_result is not None else 0,\n", " \"total_cycles\": rt_result.total_cycles if rt_result is not None else 0,\n", " \"operator_summary\": operator_summary,\n", " \"overlays\": [str(path) for path in overlay_paths],\n", " },\n", " indent=2,\n", " ) + \"\\n\"\n", ")\n", "\n", "recording_console = Console(record=True, width=110)\n", "recording_console.print(hotspot_table if hotspots else \"No hotspot data loaded.\")\n", "recording_console.save_text(str(hotspot_text))\n", "\n", "for path in (summary_csv, summary_json, hotspot_text):\n", " print(f\"{path.name}: {path.stat().st_size:,} bytes -> {path}\")\n", "print(summary_json.read_text()[:500])" ] }, { "cell_type": "markdown", "id": "320de398", "metadata": {}, "source": [ "## 13. Validate the New Walkthrough\n", "\n", "The final cell validates the safe-path objects on every run and tightens its assertions when real profile data is present. Restart the kernel and run all cells before promoting this candidate over the original walkthrough." ] }, { "cell_type": "code", "execution_count": null, "id": "24e6135e", "metadata": {}, "outputs": [], "source": [ "assert MODEL.is_file()\n", "assert MODEL.read_bytes()[4:8] == b\"TFL3\"\n", "assert doctor.checks\n", "assert engines\n", "assert boards\n", "assert cpu_counters\n", "assert resolved.model.path == MODEL\n", "assert resolved.target.board == BOARD\n", "assert resolved.target.toolchain == hpx.Toolchain.ARM_NONE_EABI_GCC\n", "assert summary_csv.is_file()\n", "assert summary_json.is_file()\n", "assert hotspot_text.is_file()\n", "assert set(fieldnames) == {\"op\", \"count\", \"total\", \"mean\", \"median\", \"p90\", \"max\"}\n", "\n", "if rt_result is not None:\n", " assert rt_result.layers\n", " assert rt_result.layer_count > 0\n", " assert timing_rows\n", " assert operator_summary\n", " assert all(hasattr(layer, \"counters\") for layer in rt_result.layers)\n", "\n", "print(\"Showcase validation passed.\")\n", "print(\"Packaged model:\", MODEL)\n", "print(\"Results directory:\", RESULTS_ROOT)" ] } ], "metadata": { "kernelspec": { "display_name": "helia-profiler", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.15" } }, "nbformat": 4, "nbformat_minor": 5 }