Impl/topic17 #257
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| 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: | | |
| python3.12 -m pip install --upgrade pip | |
| python3.12 -m pip install -e ".[all]" | |
| python3.12 -m pip install "pytest>=7,<10" | |
| # Includes Topic 9 parser, diagnostic, CLI and benchmark regression tests. | |
| - name: Run all topic tests | |
| run: | | |
| mkdir -p benchmark_reports | |
| python3.12 -m pytest tests/ -v --tb=short \ | |
| --junit-xml=benchmark_reports/test_results.xml \ | |
| --ignore=tests/test_simulator.py | |
| - name: Run assembly-beautifier regressions | |
| run: | | |
| python3.12 -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: | | |
| python3.12 -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: | | |
| python3.12 -m pytest tests/test_pr37_regression.py -v --tb=short | |
| - name: Generate test visualization page | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| python3.12 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/tests.html | |
| retention-days: 30 | |
| # ═════════════════════════════════════════════════════════════════════════ | |
| # 模型性能测试:ONNX模型管线 + DSL用例 + CNN RISC-V编译 | |
| # ═════════════════════════════════════════════════════════════════════════ | |
| benchmark: | |
| runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'self-hosted' }} | |
| timeout-minutes: 30 | |
| 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: | | |
| python3.12 -m pip install --upgrade pip | |
| python3.12 -m pip install -e ".[all]" | |
| python3.12 -m pip install markdown "pytest>=7,<10" | |
| - 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" \ | |
| --json-output benchmark_reports/dsl_diagnostics.json \ | |
| --markdown benchmark_reports/dsl_diagnostics.md \ | |
| --html benchmark_reports/dsl_diagnostics.html | |
| # ── 3.1 ONNX 模型管线基准测试 ────────────────────────────────────── | |
| - name: ONNX model pipeline benchmarks | |
| run: python3.12 -m pytest benchmarks/test_benchmark.py -v --tb=short | |
| # ── 3.1.1 课题14:固定 case + 真实 TinyFive A/B 报告 ───────────── | |
| - name: Topic 14 constant-merge case report | |
| run: | | |
| python3.12 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 | |
| # ── 3.2 DSL 用例编译 + 模拟基准 ──────────────────────────────────── | |
| - name: DSL case compilation benchmarks | |
| run: | | |
| mkdir -p benchmark_reports | |
| python3.12 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 | |
| if [ ! -f "$MODEL" ]; then | |
| echo "::warning::cnn.onnx not found, generating minimal CNN test model" | |
| python3.12 scripts/gen_minimal_cnn.py 2>&1 | |
| fi | |
| python3.12 scratchv/standalone/onnx_to_riscv_standalone.py \ | |
| "$MODEL" -o /tmp/cnn_riscv.bin \ | |
| --asm benchmark_reports/cnn_scratchv.s \ | |
| --estimate --report --const-merge | |
| # ── 3.3.1 汇编美化器:真实 CNN 输出 + Actions Summary ─────────── | |
| - name: CNN assembly beautifier benchmark | |
| run: | | |
| python3.12 -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 | |
| python3.12 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 | |
| python3.12 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" | |
| python3.12 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: | | |
| python3.12 scripts/split_cnn_to_single_ops.py \ | |
| || echo "WARNING: split_cnn_to_single_ops failed" | |
| # ── 3.6 单算子 benchmark ──────────────────────────────────────── | |
| - name: Single-operator benchmarks | |
| run: | | |
| python3.12 scripts/bench_single_ops.py \ | |
| || echo "WARNING: bench_single_ops failed" | |
| # ── 3.7 生成仪表盘 HTML (版本vsLLVM + 指令分类 + 算子对比) ───── | |
| - name: Generate dashboard | |
| run: | | |
| python3.12 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: Register allocation benchmarks | |
| run: | | |
| python3.12 -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: Upload benchmark reports | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: benchmark-reports | |
| path: benchmark_reports/ | |
| retention-days: 30 | |
| # ── 保留推广主页(docs/ScratchV.html 不会被顶替) ──────────────── | |
| - name: Copy promotional page into Pages artifact | |
| if: github.ref == 'refs/heads/main' | |
| run: cp docs/ScratchV.html benchmark_reports/ScratchV.html | |
| # ── 文档课程 HTML 站点 ────────────────────────────────────────────── | |
| - name: Build docs HTML course site | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| python3.12 -m pip install markdown | |
| python3.12 scripts/build_docs_html.py --output-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: python3.12 scratchv/ci/history_page.py -o benchmark_reports/history.html | |
| # ── 测试可视化页面 ──────────────────────────────────────────────── | |
| - name: Generate test visualization page | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| python3.12 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/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 | |
| 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 "### Register Allocation Benchmarks" >> $GITHUB_STEP_SUMMARY | |
| if [ -f benchmark_reports/regalloc_bench.md ]; then | |
| cat benchmark_reports/regalloc_bench.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 |