xilinx/ross-ai-assistant/hls-optimize
Claude Code and agent skill by xilinx/ross-ai-assistant
- community
- ext:[{"type":"config","description":"Configuration overrides"}]
Checking that the SKILL.md file is still in the repository.
Iteratively optimize the HLS kernel against a given criteria (e.g. minimize latency, reduce DSP usage, maximize throughput) by applying and measuring pragma and algorithmic changes.
Install
npx vskill@latest install xilinx/ross-ai-assistant/hls-optimizeSemi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard
SKILL.md
Skill: hls-optimize
Iteratively modify the kernel to improve performance against an optimization criteria, using the other skills to measure progress and committing each attempt.
Optimization criteria: $ARGUMENTS
Examples:
/hls-optimize minimize latency/hls-optimize minimize DSP usage while meeting timing/hls-optimize maximize throughput (minimize II)/hls-optimize reduce LUT count below 5000
Init component and git repository
MANDATORY: Before any optimization work, you MUST read and execute the ./reference/init-component.md file.
DO NOT write your own git init commands. DO NOT use simplified git commands. You MUST execute the ./reference/init-component.md file, which includes the vitis-comp.json check, specific git configuration, and .gitignore setup.
This ensures the HLS component is properly set up, with consistent git configuration, proper .gitignore setup, and correct baseline commit format across all optimization sessions.
Philosophy
One idea at a time. Each attempt changes exactly one thing — one pragma, one algorithmic transformation, one loop restructuring. Never combine independent changes in a single attempt. You cannot attribute cause if multiple things changed simultaneously.
Investigate before moving on. After each synthesis, read the reports thoroughly. Do not just check whether latency went up or down — understand why. Read the loop detail table. Check II and achieved vs. target. Look for warnings in the log. If something unexpected happened, dig into it before proceeding.
Use all available tools. The synth skill gives access to BC file inspection, QoR JSON, inferred directives, and schedule details. Use hls-component-basic-info skill and the hls-synth-report skill for a quick overview. In synthesis log to inspect how the pragma used in the code. Use ./hls-scripts/qor_log.py to track the history of changes. Verify that the change had the expected effect — not just in the report, but in the IR and schedule.
Experimental changes are valid. Sometimes the right move is to make a change that you don't expect to improve the metric, but that tests a hypothesis about the tool's behavior. Document what you expected and what actually happened. Understanding the compiler's behavior is itself valuable.
Do not rush to run cosim or impl. Use csim+csynth as the inner loop. Only escalate to cosim when csynth shows meaningful improvement (≥ 10% in cycles or a structural change like II reduction). Only run impl when cosim confirms improvement. The expensive steps are a gate, not a rubber stamp.
Verify Vitis environment.
If not found, check if the environment variable XILINX_VITIS is set. If not, ask the user for the value of XILINX_VITIS. Then source the settings file:
Do not proceed until vitis-run is on PATH.
Step 0: Establish baseline and get HLS design data
0a. Establish a baseline
Before making any change, ensure you have a measured baseline to compare against. The baseline consists of:
- cosim latency (cycles) from cosimulation report
- post-route clock period (ns) from the
hls-impl-reportskill'spostRoutevalue (implementation report) - true latency = cycles × period
- resource utilization (LUT, FF, DSP, BRAM, URAM) from the
hls-impl-reportskill'splaceRouteResourceSummaryvalue (implementation report)
When you establish the baseline, you must make sure the csimulation, synthesis, cosimulation and implementation flows have all been run successfully. If any of the reports is missing or stale, use skill of hls-run-flow to run the corresponding flow before recording the baseline.
0b. Get HLS design reports and data
MANDATORY: You MUST call the following functions to get ALL report-related data. DO NOT read .rpt files directly using file read tools — always use these functions.
hls-synth-reportskill: get the synthesis report and log content.- Returns
synthesisReportContent,synthesisPragmaReportContent, andsynthesisLogContent hls-cosim-reportskill: get the cosimulation report content and dataflow process/channel content.- Returns
coSimulationReportContentanddataflowProcessAndChannelContent hls-impl-reportskill: get the implementation report content.- Returns
postRoute,placeRouteResourceSummaryandplaceRouteFailFast
0c. Run HLS flows if reports are missing or stale
If these reports do not exist or are stale, you must use the hls-run-flow skill to run the active component HLS flow. Before running csim flow, you must check 'csim.profile_tripcount=1' in .cfg file. If it is not set, update the trip count. When you find it changes the trip count, you must run all flows (csim, csynth, cosim, impl) to get the updated reports before recording the baseline.
0d. Log the baseline QoR data for future comparison
On the unmodified kernel first.
Call getSkillResourcePath function with skillName and relativePath ./hls-scripts/qor_log.py to get the full path to the script.
Then run python3 "$qorLogScriptFullPath" --report "$synthesisReportContent" to get a concise summary of the baseline. The report argument is required; the label and csv arguments are optional. Record the baseline before starting optimization iterations.
Step 1: Analyze the kernel
You must call hls-component-basic-info skill to get the basic component info, including component_name, source_files, testbench_files, include_paths, top_function. Read this information along with the synthesisReportContent and synthesisLogContent to analyze the kernel and identify bottlenecks.
- High II on inner loops → memory port bottleneck or long recurrence chain. Check loop table for
II achievedvsII target. Read the warning messages insynthesisLogContentfor the root cause. - Large iteration latency on unpipelined loops → missing pipeline pragma, or loop not eligible for pipelining (e.g. variable trip count, non-trivial control flow, contains sub-loop).
- Low resource utilization → opportunity to trade area for performance (unrolling, partitioning). DSP at 2% means 98% of compute is still sequential.
- High resource utilization → risk of fit; verify after every change.
- Sequential outer loop containing pipelined inner loop → inner pipeline restarts on every iteration, dominant latency term.
Also read the Violation Report in the synthesisLogContent carefully — it identifies exactly which dependency causes each II violation, including the variable name and memory port.
Step 2: Form a hypothesis
Before touching any code, write down:
- What you will change (exact pragma or code transformation)
- What you expect to happen in the
synthesisReportContent(loop II, latency, resources) - What would confirm the hypothesis (e.g. "II drops from 5 to 2 because we have 2 memory ports now")
- What would falsify it (e.g. "II stays at 5 despite partition → the bottleneck is the FMA recurrence, not memory")
This forces you to understand the compiler before running it, and makes failed experiments informative.
Step 3: Choose one optimization technique
Pick one technique per attempt. See the full technique catalogue below.
Pragma-only changes (lowest risk, try first)
| Technique | Pragma | Effect | When to use | |
|---|---|---|---|---|
| Acknowledge II | #pragma HLS PIPELINE II=<N> | Prioritize II over satisfying timing pressure | II violation in csynth report (to acknowledge the real achievable II) | |
| Loop unroll (partial) | #pragma HLS UNROLL factor=<N> | Replicates loop body N times, reduces trip count by N | Inner loop with known trip count divisible by N | |
| Loop unroll (full) | #pragma HLS UNROLL | Fully unrolls loop; all iterations in parallel | Short loops (≤ 16 iterations), sufficient resources, constant loop trip count | |
| Array partition (cyclic) | #pragma HLS ARRAY_PARTITION variable=<x> cyclic factor=<N> dim=<D> | Creates N memory banks; N parallel accesses per cycle | Memory port II bottleneck | |
| Array partition (complete) | #pragma HLS ARRAY_PARTITION variable=<x> complete dim=<D> | Fully registers the array (no BRAM) | Small arrays only | |
| Array partition (block) | #pragma HLS ARRAY_PARTITION variable=<x> block factor=<N> dim=<D> | Splits into N contiguous blocks | When access pattern is block-sequential | |
| Loop flatten | #pragma HLS LOOP_FLATTEN | Merges nested loops into a single loop counter | Nested loops with loop-invariant bounds | |
| Dataflow | #pragma HLS DATAFLOW | Task-level pipelining between functions or loops | Sequential stages that can overlap, non-innerloop pipelining | |
| Expression balance | #pragma HLS EXPRESSION_BALANCE | Allow expression tree balancing on float | Floating point reductions in critical path |
Algorithmic changes (higher risk, higher reward)
| Technique | Effect | When to use | |
|---|---|---|---|
| Loop reordering | Changes memory access pattern; may improve spatial locality or expose better reuse | Poor memory reuse in inner loop; can turn random access into sequential | |
| Tiling / blocking | Reuses on-chip data, reduces off-chip bandwidth, make buffer size constant | Memory bandwidth bound, variable size data to chunk into fixed size buffer | |
| Local buffer | Stage data into local arrays to decouple memory access from compute | Repeated accesses to same memory region | |
| Scalarization | Store data into individual scalars to allow arbitrary accesses and additional simplifications | Repeated accesses to the same memory element; can allow infinite access per cycle | |
| Loop fusion | Merge two loop body into the same loop to reduce storage and allow for pipelining | Two consecutive loops with identical loop trip count working on the same buffers | |
| Loop fission | Split the loop body into two separate loop to create independent processes in dataflow context | Loop body working on independent arrays/streams causing stall or complex control | |
Replace float with ap_fixed<W,I> | Shorter pipeline, fewer DSPs, faster clock | Fixed-point arithmetic acceptable for the application | |
| Replace division with reciprocal multiply | Eliminates expensive divider | Division inside a loop by constant divisor |
HLS library usage
Step 4: Implement the change
Use the template to launch a sub-agent for each attempt. Fill in all bracketed fields before launching.
Key rules for the sub-agent:
- Make only the described change. Do not opportunistically fix other things.
- After each tool run, read the output carefully before deciding to proceed.
- If csynth warnings or loop table do not match the hypothesis, investigate before escalating.
Step 5: Investigate the result thoroughly
For run csynth, do not just check the summary. Investigate systematically:
5a. Check for ignored-pragma warnings in the HLS log
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/hls-optimize/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Extension points
configConfiguration overrides
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-optimize)