Skip to content

Track: hierarchical-dataflow upstream engagement (#588 + design discussion) #7

Description

@sunwookim028

Tracking the deferred hierarchical-dataflow upstream engagement. Neither item below is posted yet. Plan: engage upstream cornell-zhang#588 first with the draft comment, and float a design discussion later (anchored inside cornell-zhang#588 or attached to a concrete PR) rather than seeding a broad parallel discussion while the maintainer drives cornell-zhang#588.

Held item 1: draft comment for upstream cornell-zhang#588 ([Bug][Builder] Issues in Dataflow Hierarchical Design, by Fangtangtang)

Note before posting: the two repros were NOT locally reproduced; soften any reproduction claim before posting.

Thanks for the precise write-up. Both repros are clear and map to the same builder path.

On (1), agreed: the region body is recovered with inspect.getsource() and handed to ast.parse() still carrying the indentation of the enclosing kernel scope, so any region invoked from inside a kernel trips IndentationError. Dedenting the source, or passing the object straight to parse_ast as you suggest, is the right quick fix. The trigger is specifically a sub-region call sitting inside a kernel body rather than at the top level.

On (2), also agreed. Each region instantiation re-emits a func.func under the same mangled name (vadd__0 at both call sites), so the second instantiation collides. Emitting the region function once and calling it N times, or making the instantiation suffix unique per call site, both resolve it. The emit-once option also matches how the kernels are already lowered as callable functions, so it is probably the smaller change.

One framing, if useful: these two look like the same seam rather than two unrelated bugs. The builder currently assumes a kernel is an isolated unit and a region is emitted once in place, so both a sub-region invoked from within a kernel body and the same region instantiated more than once are cases the front end does not yet model. I have been keeping notes on exactly this region-composition seam (nested invocation, region reuse, region-scope shared state) from the HLS side, and would be glad to share them or help with a fix plus regression tests. Happy to send a PR for the two quick fixes above.

Held item 2: draft for a hierarchical-dataflow design discussion

Status: HELD. Category and title style still TBD (house style is bracketed [Area] titles in the General category; plain "Hierarchical dataflow architecture" was the owner's initial preference). Accurate issue mapping: cornell-zhang#561 -> faces 1 and 2; cornell-zhang#565 -> face 2; cornell-zhang#577 review -> face 4; face 3 (EmitVivadoHLS.cpp per-kernel static) has no dedicated issue.

Draft title: Hierarchical dataflow architecture

Draft body:
Both of our on-device accelerators (allo-tpu on U280/XRT and its allo-npu sibling) need the same shape: one @df.region that owns shared state (scratchpad, accumulator, instruction memory) and streams, with a decoder kernel and a driver kernel that concurrently read and write that shared state. This is the canonical HLS dataflow topology (Vitis_Libraries, FINN-hlslib, AutoSA, ScaleHLS all put shared accelerator state at the top scope and run PEs as concurrent sub-functions). It is what any programmable 2D mesh design lowered through Allo needs.

Building it today surfaces four issues that share one root cause: a @df.kernel is modeled as an IsolatedFromAbove function, so the region body cannot own state and channels that concurrent kernels share. The four faces:

  1. Simulator: sub-region calls inside control flow leave callee streams un-lowered. Tracked in [Bug] Hierarchical regions with inter-kernel streams deadlock in simulator and have HLS codegen issues cornell-zhang/allo#561; deadlock half fixed in fix: hierarchical dataflow simulator deadlock and HLS codegen (#561, #565) cornell-zhang/allo#577.
  2. Front-end: region-scope @stateful shared across inner kernels does not survive ASTContext.copy(). Tracked in [Bug] Missing global_op_cache on ASTContext.copy() cornell-zhang/allo#565 (closed via fix: hierarchical dataflow simulator deadlock and HLS codegen (#561, #565) cornell-zhang/allo#577). Shared region-scope state still not in the upstream test corpus; [Bug][Builder] Issues in Dataflow Hierarchical Design cornell-zhang/allo#588 shows hierarchical-builder bugs remain.
  3. Back-end: EmitVivadoHLS.cpp emits each stateful global as a static array inside every kernel body, so two kernels sharing one stateful buffer mis-compiles. Not yet addressed upstream.
  4. Interface: auto-captured scalar control ports get no s_axilite emission; the fix: hierarchical dataflow simulator deadlock and HLS codegen (#561, #565) cornell-zhang/allo#577 review rejected scalars in args=[...], pushing users onto auto-capture with no AXI-Lite path. Workaround is int32[1] bound as m_axi. Not yet addressed upstream.

Roadmap question: should @df.region stay a grouping of isolated kernels with state grafted on, or become a hierarchical module that owns state and channels, with kernels as concurrent processes and explicit interface bindings? The second is the industry-standard mesh model and dissolves all four faces into one design. Related live threads: cornell-zhang#588, cornell-zhang#592, cornell-zhang#524.

Next action

Post held item 1 to upstream cornell-zhang#588 (after softening the reproduction wording), then decide on the discussion venue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions