Skip to content

docs(kernels): add kernel framework docs and the LLVM interop design #404

docs(kernels): add kernel framework docs and the LLVM interop design

docs(kernels): add kernel framework docs and the LLVM interop design #404

Workflow file for this run

name: CI
on:
push:
branches: [main, wjy_dev, jzj_dev]
pull_request:
branches: [main]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
jobs:
# ═════════════════════════════════════════════════════════════════════════
# 课题功能测试:所有14个模块的单元测试 + 集成测试
# ═════════════════════════════════════════════════════════════════════════
test:
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'self-hosted' }}
timeout-minutes: 20
env:
# Pin the scheduler's timing authority so both runners agree; see the
# toolchain step below.
LLVM_MCA: llvm-mca-18
steps:
- name: Checkout pull request on isolated runner
if: github.event_name == 'pull_request'
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
# ONNX before/after integration tests read the pinned PR #89 commit.
fetch-depth: 0
- name: Set up Python for pull request
if: github.event_name == 'pull_request'
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
- name: Sync from local mirror (skip unstable GitHub checkout)
if: github.event_name != 'pull_request'
run: |
echo "=== CI Sync ==="
retry() {
local desc="$1" rc=0; shift
for i in 1 2 3; do
if "$@" --depth=1; then rc=0; break; fi
rc=$?
if [ "$i" -lt 3 ]; then
echo "::warning::$desc failed, retry #$i in $((i*3))s"
sleep $((i * 3))
else
echo "::error::$desc failed after 3 attempts"
fi
done
return $rc
}
MIRROR=/opt/ScratchV
WORKSPACE=/opt/actions-runner/_work/ScratchV/ScratchV
rm -rf "$WORKSPACE"
cp -a "$MIRROR" "$WORKSPACE"
cd "$WORKSPACE"
echo "Fetching origin main..."
retry "git fetch origin main" git fetch origin main || exit 1
echo "Checking out $GITHUB_SHA..."
if ! git -c advice.detachedHead=false checkout -f "$GITHUB_SHA"; then
echo "::warning::Checkout failed, fetching SHA directly from origin..."
git fetch origin "$GITHUB_SHA" || true
if git -c advice.detachedHead=false checkout -f "$GITHUB_SHA"; then
echo "::notice::Checkout successful after direct fetch: $(git log -1 --format='%h %ai %s')"
else
echo "::error::GITHUB_SHA ($GITHUB_SHA) not found — checkout failed"
exit 1
fi
else
echo "::notice::Checkout successful: $(git log -1 --format='%h %ai %s')"
fi
- name: Install dependencies
run: |
set -euo pipefail
if python -c 'import sys; sys.exit(0 if sys.version_info[:2] == (3, 12) else 1)'; then
PY=python
elif command -v python3.12 >/dev/null 2>&1; then
PY=python3.12
else
echo "Python 3.12 not found" >&2
exit 1
fi
echo "PY=$PY" >> "$GITHUB_ENV"
echo "Using python: $($PY -c 'import sys; print(sys.executable, sys.version)')"
$PY -m pip install --upgrade pip setuptools wheel
$PY -m pip install -e ".[all]"
$PY -m pip install "pytest>=7,<10"
- name: Run Topic 04 PassManager regressions
id: topic04_pass_manager
env:
PYTHONHASHSEED: "0"
run: |
set -euo pipefail
mkdir -p benchmark_reports
$PY -m pytest \
tests/test_pass_manager.py \
tests/test_pass_registry.py \
tests/test_optimizer.py \
tests/test_optimizer_advanced.py \
-v --tb=short \
--junit-xml=benchmark_reports/topic04_pass_manager.xml \
| tee benchmark_reports/topic04_pass_manager.txt
- name: Summarize Topic 04 PassManager results
if: always()
env:
TOPIC04_OUTCOME: ${{ steps.topic04_pass_manager.outcome }}
run: |
{
echo "## Topic 04 PassManager"
echo "Result: $TOPIC04_OUTCOME"
echo ""
echo "Coverage: pass registration, enable/disable switches, constant folding, functional pipelines, and optimizer regressions."
echo ""
echo "JUnit XML and detailed test output are included in the test-reports artifact when tests run."
} >> "$GITHUB_STEP_SUMMARY"
- name: Run IR interpreter and LICM regressions
timeout-minutes: 5
env:
PYTHONHASHSEED: "0"
OMP_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
mkdir -p benchmark_reports
$PY -m pytest tests/test_ir_interpreter*.py tests/test_licm_safety.py -q \
--junit-xml=benchmark_reports/ir_interpreter_tests.xml
- name: Prepare RISC-V test tools
run: |
set -euo pipefail
# llvm-mca is the scheduler's timing authority. The checked-in benchmark
# numbers and the scheduler test expectations are calibrated to LLVM 18.
# Ubuntu's `llvm` metapackage resolves to 14 on 22.04 and 18 on 24.04, so
# pin the major version instead of taking whatever `llvm` happens to be.
if ! command -v clang >/dev/null || ! command -v ld.lld >/dev/null \
|| ! command -v qemu-riscv32 >/dev/null || ! command -v llvm-mca-18 >/dev/null; then
# The self-hosted runner has no passwordless sudo; there the toolchain is
# provisioned out of band and the checks below are the assertion.
if sudo -n true 2>/dev/null; then
sudo apt-get update
sudo apt-get install --no-install-recommends -y clang lld qemu-user llvm-18 \
|| echo "::warning::llvm-18 is not available from this runner's repositories"
else
echo "::warning::no passwordless sudo; using the runner's preinstalled toolchain"
fi
fi
missing=""
for tool in clang ld.lld qemu-riscv32 llvm-mca-18; do
command -v "$tool" >/dev/null 2>&1 || missing="$missing $tool"
done
if [ -n "$missing" ]; then
echo "::error::missing tools:$missing -- provision them on this runner as root; CI cannot install them (no passwordless sudo)"
echo "::notice::Ubuntu 22.04's default \`llvm\` package is 14, so \`llvm-mca-18\` needs the apt.llvm.org archive; the scheduler's expectations are calibrated to LLVM 18 (docs/topics/18-指令调度器/README.md)."
exit 1
fi
$PY -c "from scratchv.backend.llvm_mca import check_version; v = check_version('llvm-mca-18'); print(v); assert 'LLVM version 18.' in v, 'scheduler timing requires LLVM 18, got: ' + v"
# Includes scheduling and standalone CNN execution regressions.
- name: Run all topic tests
env:
PYTHONHASHSEED: "0"
SCRATCHV_REQUIRE_RISCV_EXECUTION: "1"
run: |
mkdir -p benchmark_reports
$PY -m pytest tests/ -v --tb=short \
--junit-xml=benchmark_reports/test_results.xml \
--ignore=tests/test_simulator.py
- name: Topic 01 DSL frontend regressions
run: |
$PY -m pytest \
tests/test_dsl_control_flow.py \
tests/test_dsl_control_flow_benchmark.py \
-v --tb=short
- name: Run assembly-beautifier regressions
run: |
$PY -m pytest \
tests/test_parser_for_beautifier.py \
tests/test_asm_beautifier_comments.py \
tests/test_asm_beautifier_formatting.py \
tests/test_asm_beautifier_integration.py \
tests/test_asm_beautifier_blackbox.py \
-v --tb=short
- name: Run constant-merge regressions
run: |
$PY -m pytest \
tests/test_const_merge.py \
tests/test_backend.py::TestConstMergeIntegration \
tests/test_simulator.py::TestStubProfiledMachine \
-v --tb=short
- name: Run PR #37 register-allocation regressions
run: |
$PY -m pytest tests/test_pr37_regression.py -v --tb=short
- name: Run topic13 peephole regressions
run: |
$PY -m pytest tests/test_asm_peephole*.py -v --tb=short
- name: Run topic13 peephole CLI smoke
run: |
$PY -m scratchv.backend.asm_peephole --list-rules | tee /tmp/peephole_rules.txt
grep -q "addi+addi fusion" /tmp/peephole_rules.txt
if grep -q "redundant mv pair elimination" /tmp/peephole_rules.txt; then
echo "unsound rule must not be listed" >&2
exit 1
fi
$PY -m scratchv.backend.asm_peephole \
tests/fixtures/asm_peephole/input_addi_fusion.s \
-o /tmp/peephole_out.s --report --json | tee /tmp/peephole_report.json
$PY -c "import json; d=json.load(open('/tmp/peephole_report.json')); assert d['instructions_saved']>=1"
grep -q "8" /tmp/peephole_out.s
- name: Run Topic 17 register-allocation regressions
run: |
$PY -m pytest \
tests/test_regalloc_pseudo.py \
tests/test_regalloc_pseudo_benchmark.py \
tests/test_regalloc_p1.py \
tests/test_regalloc_metrics.py \
tests/test_regalloc_spill_compare.py \
tests/test_abi_frame.py \
tests/test_riscv_encoder_validation.py \
tests/test_rv32_emulator.py \
tests/test_simulator.py::TestRealProfiledMachine::test_lw_preserves_all_four_bytes \
-v --tb=short
- name: Topic 21 CNN IR verification smoke test
run: |
mkdir -p benchmark_reports/ir_verifier_smoke
for level in none basic all; do
# Verify tensor IR without invoking the scalar-only legacy backend.
$PY -m scratchv models/graph/cnn.onnx \
--backend ir --verify-ir --optimize "$level" --dump-ir \
-o "benchmark_reports/ir_verifier_smoke/cnn_${level}.ir" \
2>&1 | tee "benchmark_reports/ir_verifier_smoke/cnn_${level}.log"
test -s "benchmark_reports/ir_verifier_smoke/cnn_${level}.ir"
done
shell: bash
- name: Generate test visualization page
if: github.ref == 'refs/heads/main'
run: |
$PY scratchv/ci/test_page.py \
--junit benchmark_reports/test_results.xml \
-o benchmark_reports/tests.html
- name: Upload test reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: test-reports
path: |
benchmark_reports/test_results.xml
benchmark_reports/ir_interpreter_tests.xml
benchmark_reports/tests.html
benchmark_reports/ir_verifier_smoke/
benchmark_reports/topic04_pass_manager.xml
benchmark_reports/topic04_pass_manager.txt
retention-days: 30
# ═════════════════════════════════════════════════════════════════════════
# 模型性能测试:ONNX模型管线 + DSL用例 + CNN RISC-V编译
# ═════════════════════════════════════════════════════════════════════════
benchmark:
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'self-hosted' }}
timeout-minutes: 30
env:
# Pin the scheduler's timing authority so both runners agree; see the
# toolchain step below.
LLVM_MCA: llvm-mca-18
steps:
- name: Checkout pull request on isolated runner
if: github.event_name == 'pull_request'
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Set up Python for pull request
if: github.event_name == 'pull_request'
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"
- name: Sync from local mirror (skip unstable GitHub checkout)
if: github.event_name != 'pull_request'
run: |
echo "=== CI Sync ==="
retry() {
local desc="$1" rc=0; shift
for i in 1 2 3; do
if "$@" --depth=1; then rc=0; break; fi
rc=$?
if [ "$i" -lt 3 ]; then
echo "::warning::$desc failed, retry #$i in $((i*3))s"
sleep $((i * 3))
else
echo "::error::$desc failed after 3 attempts"
fi
done
return $rc
}
MIRROR=/opt/ScratchV
WORKSPACE=/opt/actions-runner/_work/ScratchV/ScratchV
rm -rf "$WORKSPACE"
cp -a "$MIRROR" "$WORKSPACE"
cd "$WORKSPACE"
echo "Fetching origin main..."
retry "git fetch origin main" git fetch origin main || exit 1
echo "Checking out $GITHUB_SHA..."
if ! git -c advice.detachedHead=false checkout -f "$GITHUB_SHA"; then
echo "::warning::Checkout failed, fetching SHA directly from origin..."
git fetch origin "$GITHUB_SHA" || true
if git -c advice.detachedHead=false checkout -f "$GITHUB_SHA"; then
echo "::notice::Checkout successful after direct fetch: $(git log -1 --format='%h %ai %s')"
else
echo "::error::GITHUB_SHA ($GITHUB_SHA) not found — checkout failed"
exit 1
fi
else
echo "::notice::Checkout successful: $(git log -1 --format='%h %ai %s')"
fi
- name: Install dependencies
run: |
set -euo pipefail
if python -c 'import sys; sys.exit(0 if sys.version_info[:2] == (3, 12) else 1)'; then
PY=python
elif command -v python3.12 >/dev/null 2>&1; then
PY=python3.12
else
echo "Python 3.12 not found" >&2
exit 1
fi
echo "PY=$PY" >> "$GITHUB_ENV"
echo "Using python: $($PY -c 'import sys; print(sys.executable, sys.version)')"
$PY -m pip install --upgrade pip setuptools wheel
$PY -m pip install -e ".[all]"
$PY -m pip install markdown "pytest>=7,<10"
# Topic 18 reports share the existing benchmark job and report artifact.
- name: IR interpreter execution benchmark
timeout-minutes: 5
env:
PYTHONHASHSEED: "0"
OMP_NUM_THREADS: "1"
OPENBLAS_NUM_THREADS: "1"
MKL_NUM_THREADS: "1"
run: |
$PY -m benchmarks.bench_ir_interpreter --warmup 1 --repeats 3 \
--json-output benchmark_reports/ir_interpreter.json \
--markdown benchmark_reports/ir_interpreter.md
- name: Prepare RISC-V scheduling execution tools
run: |
set -euo pipefail
# llvm-mca is the scheduler's timing authority. The checked-in benchmark
# numbers and the scheduler test expectations are calibrated to LLVM 18.
# Ubuntu's `llvm` metapackage resolves to 14 on 22.04 and 18 on 24.04, so
# pin the major version instead of taking whatever `llvm` happens to be.
if ! command -v clang >/dev/null || ! command -v ld.lld >/dev/null \
|| ! command -v qemu-riscv32 >/dev/null || ! command -v llvm-mca-18 >/dev/null; then
# The self-hosted runner has no passwordless sudo; there the toolchain is
# provisioned out of band and the checks below are the assertion.
if sudo -n true 2>/dev/null; then
sudo apt-get update
sudo apt-get install --no-install-recommends -y clang lld qemu-user llvm-18 \
|| echo "::warning::llvm-18 is not available from this runner's repositories"
else
echo "::warning::no passwordless sudo; using the runner's preinstalled toolchain"
fi
fi
missing=""
for tool in clang ld.lld qemu-riscv32 llvm-mca-18; do
command -v "$tool" >/dev/null 2>&1 || missing="$missing $tool"
done
if [ -n "$missing" ]; then
echo "::error::missing tools:$missing -- provision them on this runner as root; CI cannot install them (no passwordless sudo)"
echo "::notice::Ubuntu 22.04's default \`llvm\` package is 14, so \`llvm-mca-18\` needs the apt.llvm.org archive; the scheduler's expectations are calibrated to LLVM 18 (docs/topics/18-指令调度器/README.md)."
exit 1
fi
$PY -c "from scratchv.backend.llvm_mca import check_version; v = check_version('llvm-mca-18'); print(v); assert 'LLVM version 18.' in v, 'scheduler timing requires LLVM 18, got: ' + v"
- name: Topic 9 DSL diagnostics benchmark
env:
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
run: |
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
echo "::error::No baseline commit available for DSL comparison."
exit 1
fi
git fetch origin "$BASE_SHA" --depth=1
BASELINE=$(mktemp -d "$RUNNER_TEMP/dsl-baseline.XXXXXX")
git worktree add --detach "$BASELINE" "$BASE_SHA"
trap 'git worktree remove --force "$BASELINE"' EXIT
python3.12 -m benchmarks.bench_dsl_diagnostics \
--baseline-root "$BASELINE" \
--allow-input-registration \
--allow-ir-change 016_if_simple.dsl \
--allow-ir-change 017_while_sum.dsl \
--allow-ir-change 018_nested_if.dsl \
--allow-ir-change 021_dsl_if_else.dsl \
--allow-ir-change 022_dsl_while_sum.dsl \
--json-output benchmark_reports/dsl_diagnostics.json \
--markdown benchmark_reports/dsl_diagnostics.md \
--html benchmark_reports/dsl_diagnostics.html
- name: Topic 01 DSL frontend benchmark
run: |
$PY -m benchmarks.bench_dsl_control_flow \
--repeats 20 \
--json-output benchmark_reports/topic01_control_flow.json \
--markdown benchmark_reports/topic01_control_flow.md \
--html benchmark_reports/topic01_control_flow.html
# ── 3.1 ONNX 模型管线基准测试 ──────────────────────────────────────
- name: ONNX model pipeline benchmarks
run: $PY -m pytest benchmarks/test_benchmark.py -v --tb=short
- name: Topic 21 CNN compilation with IR verification
run: |
$PY -m benchmarks.bench_ir_verifier \
--model models/graph/cnn.onnx --warmup 1 --repeats 5 \
--json-output benchmark_reports/ir_verifier.json \
--markdown benchmark_reports/ir_verifier.md
# ── 3.1.1 课题14:固定 case + 真实 TinyFive A/B 报告 ─────────────
- name: Topic 14 constant-merge case report
run: |
$PY benchmarks/run_const_merge_case.py \
benchmarks/cases/const_merge_feature.asm \
--json benchmark_reports/const_merge_report.json \
--markdown benchmark_reports/const_merge_report.md
# ── 课题18:固定用例执行验证与独立合成规模测试 ─────────────────
- name: Topic 18 scheduling case report
run: |
$PY -m benchmarks.run_inst_scheduler_case \
--json benchmark_reports/inst_scheduler_report.json \
--markdown benchmark_reports/inst_scheduler_report.md
- name: Topic 18 synthetic scheduling benchmark
run: |
$PY -m benchmarks.bench_inst_scheduler --repeats 3 \
--json benchmark_reports/inst_scheduler_synthetic.json \
--markdown benchmark_reports/inst_scheduler_synthetic.md
# ── 3.1.2 课题13:窥孔前后对比报告 ─────────────────────────────
- name: Topic 13 peephole compare report
run: make -s ci-peephole
# ── 3.2 DSL 用例编译 + 模拟基准 ────────────────────────────────────
- name: DSL case compilation benchmarks
run: |
mkdir -p benchmark_reports
$PY benchmarks/bench_runner.py benchmarks/cases \
--output-json benchmark_reports/dsl_bench.json \
--output-html benchmark_reports/dsl_bench.html \
--output-md benchmark_reports/dsl_bench.md
# ── 3.3 CNN RISC-V 编译 + 性能估算 ────────────────────────────────
- name: CNN RISC-V compilation & estimation
run: |
mkdir -p benchmark_reports models/graph
MODEL=models/graph/cnn.onnx
test -f "$MODEL"
$PY -m scratchv.standalone.onnx_to_riscv_standalone \
"$MODEL" -o /tmp/cnn_riscv.bin \
--asm benchmark_reports/cnn_scratchv.s \
--estimate --report --const-merge
- name: Topic 18 CNN scheduling benefit and side effects
env:
PYTHONHASHSEED: "0"
run: |
$PY -m benchmarks.bench_cnn_schedule \
--model models/graph/cnn.onnx \
--standalone-asm benchmark_reports/cnn_scratchv.s \
--llvm-mca llvm-mca-18 \
--json benchmark_reports/inst_scheduler_cnn.json \
--markdown benchmark_reports/inst_scheduler_cnn.md
# ── 3.3.1 汇编美化器:真实 CNN 输出 + Actions Summary ───────────
- name: CNN assembly beautifier benchmark
run: |
$PY -m benchmarks.bench_asm_beautifier \
--input benchmark_reports/cnn_scratchv.s \
--output-asm benchmark_reports/cnn_pretty.s \
--markdown benchmark_reports/asm_beautifier_summary.md \
--json benchmark_reports/asm_beautifier_summary.json \
--repeats 20
# ── 3.4 LLVM vs ScratchV + TinyFive + Dashboard ──────────────────
- name: LLVM vs ScratchV comparison
run: |
mkdir -p benchmark_reports
# Generate ScratchV assembly if not already present
if [ ! -f benchmark_reports/cnn_scratchv.s ] && [ -f models/graph/cnn.onnx ]; then
$PY scratchv/standalone/onnx_to_riscv_standalone.py \
models/graph/cnn.onnx -o /tmp/cnn_riscv.bin \
--asm benchmark_reports/cnn_scratchv.s --estimate \
--const-merge 2>&1 | tail -3
fi
$PY scratchv/standalone/llvm_cache_compare.py \
--json-output benchmark_reports/llvm_vs_scratchv.json \
--markdown benchmark_reports/llvm_vs_scratchv.md \
|| echo "WARNING: llvm_cache_compare failed"
$PY scratchv/standalone/tinyfive_compare.py \
--json benchmark_reports/tinyfive_compare.json \
--markdown benchmark_reports/tinyfive_compare.md \
--scratchv-asm benchmark_reports/cnn_scratchv.s \
|| echo "WARNING: tinyfive_compare failed"
# ── 3.5 ONNX 模型拆分为单算子 ────────────────────────────────────
- name: Split CNN model into single operators
run: |
$PY scripts/split_cnn_to_single_ops.py \
|| echo "WARNING: split_cnn_to_single_ops failed"
# ── 3.6 单算子 benchmark ────────────────────────────────────────
- name: Single-operator benchmarks
run: |
$PY scripts/bench_single_ops.py \
--output-json benchmark_reports/single_op_bench.json \
--output-md benchmark_reports/single_op_bench.md \
--pressure-regs 2,3,5,8,12,19
# ── 3.7 生成仪表盘 HTML (版本vsLLVM + 指令分类 + 算子对比) ─────
- name: Generate dashboard
run: |
$PY scratchv/ci/dashboard.py \
--llvm-json benchmark_reports/llvm_vs_scratchv.json \
--history-json benchmark_reports/optimization_history.json \
-o benchmark_reports/dashboard.html \
|| echo "WARNING: dashboard generation failed"
# ── 3.8 寄存器分配 benchmark(线性扫描:simple/dense/cnn + LLVM对比) ──
- name: Topic 17 register-allocation before/after benchmark
run: |
$PY -m benchmarks.test_regalloc.bench_regalloc_linear \
--repeats 30 \
--output-json benchmark_reports/regalloc_bench.json \
--output-html benchmark_reports/regalloc_bench.html \
--output-md benchmark_reports/regalloc_bench.md
- name: Topic 17 spill-pressure comparison
run: |
$PY -m benchmarks.bench_regalloc_spill_compare \
--json-output benchmark_reports/regalloc_spill_compare.json \
--markdown benchmark_reports/regalloc_spill_compare.md
# ── 上报 ──────────────────────────────────────────────────────────
- name: Upload benchmark reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: benchmark-reports
path: |
benchmark_reports/
!benchmark_reports/peephole_benchmark.html
!benchmark_reports/peephole_compare.json
!benchmark_reports/peephole_compare_html.json
!benchmark_reports/peephole_raw.json
!benchmark_reports/cnn_peephole_compare.json
!benchmark_reports/peephole_summary.md
retention-days: 30
- name: Upload peephole benchmark report
if: always()
uses: actions/upload-artifact@v4
with:
name: peephole-benchmark-report
path: |
benchmark_reports/peephole_benchmark.html
benchmark_reports/peephole_compare.json
benchmark_reports/peephole_compare_html.json
benchmark_reports/peephole_raw.json
benchmark_reports/cnn_peephole_compare.json
benchmark_reports/peephole_summary.md
if-no-files-found: error
retention-days: 30
# ── 保留推广主页(docs/promo/ScratchV.html 不会被顶替) ───────────
- name: Copy promotional page into Pages artifact
if: github.ref == 'refs/heads/main'
run: cp docs/promo/ScratchV.html benchmark_reports/ScratchV.html
# ── 文档课程 HTML 站点 ──────────────────────────────────────────────
- name: Build docs HTML course site
if: github.ref == 'refs/heads/main'
run: |
$PY -m pip install markdown
$PY scripts/build_docs_html.py --output-dir benchmark_reports/docs
$PY scripts/check_docs_links.py --html-dir benchmark_reports/docs
echo "Docs site built: benchmark_reports/docs/index.html"
# ── 优化历史页面 ──────────────────────────────────────────────────
- name: Generate optimization history page
if: github.ref == 'refs/heads/main'
run: $PY scratchv/ci/history_page.py -o benchmark_reports/history.html
# ── 测试可视化页面 ────────────────────────────────────────────────
- name: Generate test visualization page
if: github.ref == 'refs/heads/main'
run: |
$PY scratchv/ci/test_page.py \
--junit benchmark_reports/test_results.xml \
-o benchmark_reports/tests.html
# ── 精简 Pages 产物(移除大型编译产物) ──────────────────────────
- name: Clean large binaries before Pages deploy
if: github.ref == 'refs/heads/main'
run: |
rm -f benchmark_reports/*.bin benchmark_reports/*.elf
rm -f benchmark_reports/*.ll
rm -f benchmark_reports/cnn.onnx_*
rm -f benchmark_reports/_ll_* benchmark_reports/_sv.*
echo "Cleaned large binaries from Pages artifact"
# ── 上传 Pages 产物 ──────────────────────────────────────────────
- name: Upload Pages artifact
if: github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with:
path: benchmark_reports/
- name: Write job summary
if: always()
run: |
if [ -f benchmark_reports/ir_interpreter.md ]; then
cat benchmark_reports/ir_interpreter.md >> "$GITHUB_STEP_SUMMARY"
fi
if [ -f benchmark_reports/topic01_control_flow.md ]; then
cat benchmark_reports/topic01_control_flow.md >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ -f benchmark_reports/dsl_diagnostics.md ]; then
cat benchmark_reports/dsl_diagnostics.md >> "$GITHUB_STEP_SUMMARY"
fi
if [ -f benchmark_reports/const_merge_report.md ]; then
cat benchmark_reports/const_merge_report.md >> $GITHUB_STEP_SUMMARY
fi
for report in inst_scheduler_report inst_scheduler_cnn inst_scheduler_synthetic; do
if [ -f "benchmark_reports/$report.md" ]; then
cat "benchmark_reports/$report.md" >> "$GITHUB_STEP_SUMMARY"
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/peephole_summary.md ]; then
cat benchmark_reports/peephole_summary.md >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/github_summary.md ]; then
cat benchmark_reports/github_summary.md >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/asm_beautifier_summary.md ]; then
cat benchmark_reports/asm_beautifier_summary.md >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "### LLVM vs ScratchV" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/llvm_vs_scratchv.md ]; then
tail -20 benchmark_reports/llvm_vs_scratchv.md >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Topic 17 Register Allocation" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/regalloc_bench.md ]; then
cat benchmark_reports/regalloc_bench.md >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
if [ -f benchmark_reports/regalloc_spill_compare.md ]; then
cat benchmark_reports/regalloc_spill_compare.md >> $GITHUB_STEP_SUMMARY
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ -f benchmark_reports/single_op_bench.md ]; then
cat benchmark_reports/single_op_bench.md >> "$GITHUB_STEP_SUMMARY"
fi
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ -f benchmark_reports/ir_verifier.md ]; then
cat benchmark_reports/ir_verifier.md >> "$GITHUB_STEP_SUMMARY"
fi
# ═════════════════════════════════════════════════════════════════════════
# GitHub Pages 部署 (仅 main 分支)
# ═════════════════════════════════════════════════════════════════════════
deploy-pages:
needs: benchmark
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4