Skip to content

feat(ptodsl): support source-backed jit kernels#892

Merged
zhangstevenunity merged 3 commits into
hw-native-sys:mainfrom
Zhendong404:feature-ptodsl-explicit-source
Jul 2, 2026
Merged

feat(ptodsl): support source-backed jit kernels#892
zhangstevenunity merged 3 commits into
hw-native-sys:mainfrom
Zhendong404:feature-ptodsl-explicit-source

Conversation

@Zhendong404

Copy link
Copy Markdown
Collaborator

Summary

This PR lets PTODSL launch a hand-written PTO source file through the existing
@pto.jit runtime path by adding source=... support to launchable entry
kernels.

It keeps the Python function signature as the host ABI declaration, skips
tracing the Python body when source is provided, and validates that the
selected PTO entry matches the declared ABI before native build and launch.

What Changed

  • add @pto.jit(source=...) support for launchable entry kernels
  • resolve relative source paths against the declaring Python file
  • parse PTO source with the existing PTODSL MLIR context
  • select exactly one matching non-declaration func.func by JIT name
  • validate parameter count, parameter types, and void return type against the
    Python KernelSignature
  • reject unsupported first-version combinations:
    • entry=False
    • keyword-only pto.const_expr
    • .compile(...) constexpr bindings
  • thread source-backed native build overrides:
    • --pto-backend=<backend>
    • mode="explicit" -> --pto-level=level3
    • existing insert-sync policy remains intact
  • extend docs/tests for diagnostics, cache keys, docs-as-test, and native build
    command coverage
  • convert test/vpto/cases/micro-op/a5-extra/vmadd into a PTODSL
    source-backed runtime case using the existing kernel.pto

Validation

  • python3 ptodsl/tests/test_jit_compile.py
  • python3 ptodsl/tests/test_jit_diagnostics.py
  • PTOAS_ENV_SKIP_SMOKE_TEST=1 WORK_SPACE=/tmp/pto-vpto-ptodsl-vmadd-pr CASE_NAME='micro-op/a5-extra/vmadd' DEVICE=SIM test/vpto/scripts/run_host_vpto_validation.sh

@Zhendong404
Zhendong404 marked this pull request as ready for review July 1, 2026 14:55
@reedhecre

reedhecre commented Jul 1, 2026

Copy link
Copy Markdown

Codex Review

该评论由 review 机器人自动更新。

  • PR: feat(ptodsl): support source-backed jit kernels #892 feat(ptodsl): support source-backed jit kernels
  • Author: Zhendong404
  • Base/Head: main / feature-ptodsl-explicit-source
  • Head SHA: 6f7ad0b8733e
  • Trigger: PR 有新提交
  • Generated At: 2026-07-02T03:20:44Z
  • Previous Head SHA: 7e1736bec012
  • Status: failed at codex-review (exit=1)

Summary

Review failed at stage codex-review: exit=1

Findings

未生成结构化 findings,因为 review 过程提前失败。

Log Tail

6f7ad0b8733ea45ebf25ff6a5528c679f0373127
 .../user_guide/03-kernel-entry-and-subkernels.md   | 107 ++++++++++
 ptodsl/ptodsl/_diagnostics.py                      |  75 +++++++
 ptodsl/ptodsl/_jit.py                              |  20 ++
 ptodsl/ptodsl/_kernel_compilation.py               |  39 +++-
 ptodsl/ptodsl/_runtime/native_build.py             |  16 ++
 ptodsl/ptodsl/_source_loader.py                    | 205 ++++++++++++++++++
 ptodsl/ptodsl/_tracing/artifacts.py                |  10 +-
 ptodsl/ptodsl/_tracing/module_builder.py           |   1 +
 ptodsl/tests/support/docs_fragment_fixtures.py     |  21 ++
 ptodsl/tests/test_docs_as_test.py                  |  73 +++++--
 ptodsl/tests/test_jit_compile.py                   | 237 ++++++++++++++++++++-
 ptodsl/tests/test_jit_diagnostics.py               | 215 +++++++++++++++++++
 .../a5-extra/{vmadd/kernel.pto => vmadd.py}        |  88 +++++++-
 test/vpto/cases/micro-op/a5-extra/vmadd/compare.py |  59 -----
 test/vpto/cases/micro-op/a5-extra/vmadd/golden.py  |  40 ----
 test/vpto/cases/micro-op/a5-extra/vmadd/launch.cpp |  45 ----
 test/vpto/cases/micro-op/a5-extra/vmadd/main.cpp   | 120 -----------
 test/vpto/scripts/run_host_vpto_validation.sh      | 146 ++++++++++---
 .../scripts/run_host_vpto_validation_parallel.sh   |  83 ++++++--
 19 files changed, 1255 insertions(+), 345 deletions(-)
===== END STAGE clone rc=0 @ 2026-07-02 11:20:34 =====

===== STAGE codex-review @ 2026-07-02 11:20:34 =====
set -euo pipefail
cd '/tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/repo'
'codex' exec -C '/tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/repo' -s read-only -c 'model_provider="codereview"' -c 'model="gpt-5.4"' -c 'model_reasoning_effort="xhigh"' --output-schema '/tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/review_schema.json' -o '/tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/codex_last_message.json' --color never - < '/tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/review_prompt.txt'
[monitor] stage timeout: 1800s
OpenAI Codex v0.115.0 (research preview)
--------
workdir: /tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/repo
model: gpt-5.4
provider: codereview
approval: never
sandbox: read-only
reasoning effort: xhigh
reasoning summaries: none
session id: 019f20d7-b52f-73b3-a246-136aed932f8d
--------
user
你现在在审查 GitHub PR。

仓库:hw-native-sys/PTOAS
PR:#892 feat(ptodsl): support source-backed jit kernels
作者:Zhendong404
base branch:origin/main
head branch:HEAD(当前已 checkout 到 PR head)

要求:
1. 只审查这个 PR 相对 origin/main 的改动,必要时可以看上下文文件。
2. 重点找真实的 correctness / regression / contract mismatch / CI / runtime / compatibility 问题。
3. 不要提纯风格建议,不要提低价值猜测。
4. 严格按优先级输出:
   - P1:高概率会导致错误结果、编译/运行失败、严重回归、发布阻断
   - P2:重要缺陷、行为回归、遗漏校验/测试、较大兼容性问题
   - P3:次要但明确可改的问题
5. 如果没有问题,summary 直接写:未检查到 PR #892 存在问题,并返回 findings=[]。
6. 如果有问题,summary 简洁概括,findings 里每条都要给出:
   - severity
   - title
   - body(说明为什么是问题,尽量具体)
   - file(尽量给相对路径)
   - line(能确定就填整数,否则 null)

建议先查看:
- git status --short
- git diff --stat origin/main...HEAD
- git diff --unified=80 origin/main...HEAD

最终输出必须严格匹配 JSON schema。

mcp startup: no servers
Reconnecting... 1/5 (unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a83f69920c090-SJC, request id: 39ae9a5d-2c76-4cd0-8f8d-d2b7a42c1444)
Reconnecting... 2/5 (unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a83fa0dfd1422-SJC, request id: 5888c6db-15bf-4286-b3a8-093c2d2b8b7c)
Reconnecting... 3/5 (unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a83febb7d3bb9-LAX, request id: ade3ebd0-5132-4b92-90c7-f4cdc61c6e70)
Reconnecting... 4/5 (unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a8406584d2719-LAX, request id: d21e8ec1-bf22-4cfb-b1b3-bb66e597cc87)
Reconnecting... 5/5 (unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a84131c884c71-SJC, request id: 5c29a574-2e70-45a8-90c6-ff68f11d1ee8)
ERROR: unexpected status 403 Forbidden: {"code":"INSUFFICIENT_BALANCE","message":"Insufficient account balance"}, url: https://codex.0u0o.com/responses, cf-ray: a14a84292ac451ae-LAX, request id: 6134fb15-881e-4440-8edd-4ffcc4b5fc8b
Warning: no last agent message; wrote empty content to /tmp/ptoas-pr-review-monitor/runs/20260702_112027_pr892/codex_last_message.json
===== END STAGE codex-review rc=1 @ 2026-07-02 11:20:44 =====

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for loading existing hand-written PTO files in PTODSL using the source parameter in the @pto.jit decorator. This allows users to maintain a Python signature as the host ABI declaration while loading the kernel implementation directly from a PTO IR file instead of tracing the Python body. The changes include comprehensive diagnostics, a new SourceModuleLoader for parsing and ABI verification, integration with the compilation and native build pipelines, and extensive test coverage. The review feedback highlights critical robustness improvements, specifically addressing potential AttributeError crashes in _walk_ops and _select_entry when handling raw MLIR operations, as well as a potential NameError in the test suite due to a missing tempfile import.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +171 to +176
def _walk_ops(root_op):
for region in root_op.regions:
for block in region.blocks:
for op in block.operations:
yield op
yield from _walk_ops(op.operation)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The recursive helper _walk_ops assumes that every operation yielded by block.operations is an OpView subclass (which has an .operation attribute). However, if the source file contains unregistered operations or operations from dialects that are not loaded, block.operations will yield raw mlir.ir.Operation objects. Calling op.operation on a raw Operation will raise an AttributeError and crash the loader.\n\nWe should make _walk_ops robust by checking if the object has an operation attribute before accessing it, or by passing the raw operation to the recursive call.

Suggested change
def _walk_ops(root_op):
for region in root_op.regions:
for block in region.blocks:
for op in block.operations:
yield op
yield from _walk_ops(op.operation)
def _walk_ops(root_op):
op = root_op.operation if hasattr(root_op, "operation") else root_op
for region in op.regions:
for block in region.blocks:
for nested_op in block.operations:
yield nested_op
yield from _walk_ops(nested_op)

Comment thread ptodsl/ptodsl/_source_loader.py Outdated
Comment on lines +113 to +121
def _select_entry(self, module: Module, resolved_path: Path):
matches = []
for op in _walk_ops(module.operation):
if op.operation.name != "func.func":
continue
if getattr(op, "is_external", False):
continue
if _symbol_name(op) == self._module_spec.function_name:
matches.append(op)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Similarly to _walk_ops, _select_entry accesses op.operation.name directly. If op is a raw mlir.ir.Operation (e.g., an unregistered operation), this will raise an AttributeError. We should resolve the raw operation safely before checking its name.

Suggested change
def _select_entry(self, module: Module, resolved_path: Path):
matches = []
for op in _walk_ops(module.operation):
if op.operation.name != "func.func":
continue
if getattr(op, "is_external", False):
continue
if _symbol_name(op) == self._module_spec.function_name:
matches.append(op)
def _select_entry(self, module: Module, resolved_path: Path):
matches = []
for op in _walk_ops(module.operation):
raw_op = op.operation if hasattr(op, "operation") else op
if raw_op.name != "func.func":
continue
if getattr(op, "is_external", False):
continue
if _symbol_name(op) == self._module_spec.function_name:
matches.append(op)

yield None
return

with tempfile.TemporaryDirectory() as temp_dir:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If tempfile is not imported in this file, calling tempfile.TemporaryDirectory() will raise a NameError. You can import tempfile inline to make this context manager self-contained and robust.

Suggested change
with tempfile.TemporaryDirectory() as temp_dir:
import tempfile
with tempfile.TemporaryDirectory() as temp_dir:

@zhangstevenunity zhangstevenunity left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the source-backed @pto.jit path end-to-end: the loader (resolve/parse/select/ABI-verify), specialization-cache identity, native-build flag overrides, the docs-as-test files harness, and the vpto case-discovery rewrite. The feature is well-built and the Python test coverage is thorough. No blocking issues; two items below.

Note on the existing automated reviews:

  • The Codex bot run failed on INSUFFICIENT_BALANCE and produced no findings.
  • All three Gemini findings are false positives:
    • _walk_ops / _select_entry "raw Operation has no .operation" (HIGH x2): incorrect. mlir.ir.Operation exposes .operation (returns self), so op.operation.name and the recursive _walk_ops(op.operation) are safe for both Operation and OpView. Additionally make_context() does not allow unregistered dialects, so Module.parse rejects unknown ops before _walk_ops runs; and the ABI path already depends on the typed FuncOp view (entry.type.inputs), which the passing count/type/void diagnostics tests confirm is present.
    • tempfile NameError (MEDIUM): test_docs_as_test.py already imports tempfile (line 20) and contextmanager (line 10).

My own findings are posted inline (1x P2 validation reproducibility, 1x P3 diagnostic gap).

[[ -f "${requested_dir}/kernel.pto" ]] ||
die "case ${CASE_NAME} must provide kernel.pto"
local requested_path="${CASES_ROOT}/${CASE_NAME}"
[[ -e "${requested_path}" ]] || die "unknown case: ${CASE_NAME}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: the PR's documented SIM validation command no longer resolves against the final layout.

The vmadd case was flattened from a directory (micro-op/a5-extra/vmadd/) to a single file (micro-op/a5-extra/vmadd.py), but the Validation section still runs:

CASE_NAME='micro-op/a5-extra/vmadd' ... run_host_vpto_validation.sh

With the new resolution logic, CASE_NAME is matched by the exact -e "${CASES_ROOT}/${CASE_NAME}" test on this line. micro-op/a5-extra/vmadd no longer exists (it is vmadd.py), so this dies with "unknown case: micro-op/a5-extra/vmadd". The correct name is now micro-op/a5-extra/vmadd.py.

Please either (a) update the recorded command to CASE_NAME='micro-op/a5-extra/vmadd.py' and confirm the SIM run passes on the final file-based case, or (b) accept the extension-less basename (append .py when the bare path is absent). As written, the only device/SIM validation for this feature cannot be reproduced from the PR's own command, which suggests the final flattened layout may not have been re-run.

content_digest = hashlib.sha256(mlir_text.encode("utf-8")).hexdigest()
ctx = make_context()
with ctx, Location.unknown():
module = Module.parse(mlir_text)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: malformed PTO source bypasses the friendly jit_source_* diagnostics.

The loader wraps file-not-found (jit_source_file_error), entry selection (jit_source_entry_error), and ABI mismatch (jit_source_abi_error) in named diagnostics that quote source= and the resolved path. But a syntactically invalid source file makes Module.parse(mlir_text) raise a bare mlir.ir.MLIRError that names neither the source= argument nor the resolved path -- which is a very likely first failure when hand-editing a .pto file. Consider catching the parse failure here and re-raising through a jit_source_* helper. Same spot: the module.operation.verify() result on line 90 is discarded, so a parse-clean-but-invalid module is handed to the native build without a friendly message.

@zhangstevenunity
zhangstevenunity merged commit 0bf004d into hw-native-sys:main Jul 2, 2026
10 checks passed
@reedhecre

Copy link
Copy Markdown

A3 板测完成(有跳过)

  • 触发方式:merged
  • 源码提交:0bf004d285ee
  • 结果汇总:OK 220 / FAIL 0 / SKIP 2
  • 日志:/home/zhongxuan/ptoas-board-monitor/runtime/logs/20260702_163806_merged_pr892.log
  • LLVM cache:/home/zhongxuan/ptoas-board-monitor/cache/llvm-project-vpto-llvm21/build-shared
  • 结果 TSV:/home/zhongxuan/ptoas-board-monitor/runtime/logs/20260702_163806_merged_pr892.tsv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants