xilinx/ross-ai-assistant/hls-pipe-decomp
Claude Code and agent skill by xilinx/ross-ai-assistant
- community
Checking that the SKILL.md file is still in the repository.
Decompose a Vitis HLS pipelined region that accesses many streams into a linear chain of smaller sub-pipelines inside a dataflow region, to reduce pipeline-control complexity and improve timing. Keywords: pipeline, dataflow, stream, FIFO, timing, frequency, split pipeline, decompose
Install
npx vskill@latest install xilinx/ross-ai-assistant/hls-pipe-decompSKILL.md
Skill: hls-pipe-decomp
Refactor a Vitis HLS pipelined region with many hls::stream<> / m_axi ports into a linear chain of smaller sub-pipelines under #pragma HLS dataflow. Each sub-pipeline has simpler pipeline-control logic and meets timing more easily.
Reference: Vitis HLS User Guide (UG1399) — Dataflow Optimization chapter
When to use
Trigger on explicit /hls-pipe-decomp OR on phrases like "split this pipeline", "lots of streams in one pipelined loop", "control signals on critical path", "FIFO/MAXI status in logic levels". Input from the user: a function name + file, OR a <file>:<LOOP_LABEL> pair.
Refuse and explain if the candidate function:
- Is neither a pipelined function nor contains a pipelined inner loop (i.e. no
#pragma HLS PIPELINEon the function and none on any inner loop). - Touches ≤ 4 streaming ports total (decomposition unlikely to help).
- Contains a feedback FIFO (a local
hls::stream<>both read AND written inside the pipelined region — function or loop body). HLS accepts this pattern, but this skill does not transform it.
Invariants (MUST / MUST NOT)
- MUST form a linear chain. No fork-join. Exactly one stream between each pair of adjacent stages.
- MUST forward the full upstream packet through middle stages even if only part is consumed. Last stage may drop the forwarding output. Filtering in the middle introduces bubbles.
- MUST preserve the outer function signature exactly. Callers must not need to change.
- MUST NOT regress II. Each sub-pipeline's II ≤ the original. If you can't meet this, recurse (further-decompose the offending stage) instead of accepting the regression.
- MUST NOT access the same RAM from two sub-stages. If detected, refuse the split and ask the user to choose which stage keeps the RAM.
- Intermediate FIFO depth = 2 (the default RAW latency is 1). Do not enlarge unless the user explicitly asks.
- Use a neutral typedef suffix (e.g.
_pkt). - New helpers go in the same file as the original function (above its definition).
Workflow
Confirm with the user at each phase boundary. Skip per-phase confirmation only if the user says auto or proceed without asking.
- Locate. Read the file(s); find the target function.
- Analyze. Enumerate every
hls::stream<>,m_axi/pointer, RAM access, scalar used in addressing, the existing#pragma HLS PIPELINE II=?, and the trip count (static or stream/scalar-controlled). Classify each stream as input or output. If any local stream is both read AND written inside the pipelined region (function or loop body), stop and refuse (feedback FIFO; out of scope). Report inventory; get sign-off. - Propose chain. Default: Read → Process → Write. If Read or Write would still touch > ~8 narrow streams or > ~4 wide MAXI ports, propose further-decomposing that part (see The core transform below). Render the proposal as
A → (s1) → B → (s2) → C → … → Zwith the stream count each stage will touch. Get sign-off. - Design packet. For each intermediate stream, define a packet type carrying every field that crosses the stage boundary:
- Prefer a
structwith#pragma HLS aggregate(orhls::vector<T, N>when the payload is N homogeneous elements) — cleaner than manual bit-packing. Fall back to a packedap_uint<>only when a struct is awkward. - Dynamic trip count seen by downstream → add a 1-bit end-of-stream flag field (e.g. a
boolin the struct).
Show the packet layout. Get sign-off.
- Generate helpers. Insert new helper functions into the same file, above the original. Each helper: takes its intermediate streams by reference; inner loop marked
#pragma HLS PIPELINE II=1(or matching original II);#pragma HLS UNROLLon per-stream inner loops, as the original did; forwards the upstream packet (except for the last stage in a chain). Use a template parameter (<int start, int end>,<int bank>,<int GROUP_ID>) when a stage handles a contiguous range/bank/group. - Wire dataflow region. Replace the original function body with
#pragma HLS dataflow+ intermediate stream declarations + the chain of helper calls. Preserve the outer signature exactly. - Add stream-depth pragmas.
#pragma HLS STREAM variable=<name> depth=2on every intermediate stream. Do not enlarge unless the user asks. - (Optional) Recurse. If a sub-stage still has too many streams, apply steps 3-7 to it. A Process stage may itself become a
#pragma HLS dataflowcontaining one sub-process per resource (e.g. one per DDR channel). - Summary report. Emit a manual-verification checklist: stages created, intermediate streams + depths, new typedefs, "outer signature preserved? (yes is expected)", "II preserved? (vitis_hls verifies)", "any RAM shared across new stages? (flag if yes)", "next: csim → csynth_design → check II → check timing", and a note that dataflow control logic itself may become the new bottleneck.
This skill does NOT run vitis_hls, csim, csynth, or any synthesis tool. The user verifies II and timing.
The core transform
Pack the inputs into a packet, then build a linear chain of stages connected by exactly one stream each. Every stage reads a packet, handles only its own subset of the work, and forwards the full packet downstream; the last stage does not forward. Two independent choices specialize each stage:
- Subset selection — a static range of ports (
for j in [START,END]unrolled),
OR a runtime tag carried in the packet (if (tag's group == THIS_STAGE)).
- Termination — a static loop bound when the trip count is known, OR a 1-bit
end-of-stream flag field in the packet when it is dynamic.
A sub-stage that still has too many ports is decomposed the same way recursively (this is how a 2D banks × slots array is handled — range-split applied twice).
Example 1 — static range, fan-in: each stage reads a range of input streams and packs them.
Example 2 — runtime tag, fan-out: each stage reads one packet stream and routes to a subset of the output streams by a runtime id.
For a dynamic trip count, drive the loop from the packet's end-of-stream flag instead of a fixed bound.
Common failure modes
| Situation | Response | |
|---|---|---|
| Function not found in file | Ask user to confirm name/path; offer fuzzy matches. | |
| Function already in dataflow | Show current structure; ask if user wants to further-decompose a sub-stage. | |
| Target is a pipelined loop nested in a larger function | Extract it into its own function first, then proceed. | |
| Feedback FIFO in the pipelined region (stream read AND written inside the function or loop body) | Refuse; out of scope. | |
| Stream type uses an opaque custom typedef | Read the header(s); if still ambiguous, ask user for the underlying width. | |
| Dynamic trip count and downstream needs it | Use a 1-bit end-of-stream flag in the packet; call it out in the packet design. | |
| Same RAM accessed from two intended stages | Refuse the split; ask user which stage keeps the RAM. | |
Original signature has unusual types (e.g. T (&arr)[N]) | Preserve verbatim. Do not "improve" them. |
Success criteria
Done when: the diff was applied, outer signature unchanged, the chain matches what the user signed off on, no fork-join, no RAM shared across stages, and the summary checklist was emitted. II/timing verification is the user's responsibility — if they report II regression, deadlock, or mismatch after csynth_design, walk back through steps 4-7 with them; the usual bugs are missing forwarding, mis-sized intermediate FIFO, or accidentally-shared RAM.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/hls-pipe-decomp/SKILL.md
Popularity
- Repository stars
- 219
- Repository forks
- 28
- 7-day trend score
- 0
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/xilinx/ross-ai-assistant/hls-pipe-decomp)