xilinx/ross-ai-assistant/hls-matlab-to-cpp

Claude Code and agent skill by xilinx/ross-ai-assistant

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Convert MATLAB sample-based code to plain C++ frame-based loops — analyze algorithm, generate C++ that compiles with g++, verify against MATLAB golden, then hand off to /hls-architect for HLS dataflow architecture.

Install

npx vskill@latest install xilinx/ross-ai-assistant/hls-matlab-to-cpp

SKILL.md

MATLAB to C++ Conversion

Convert MATLAB sample-based algorithms into frame-based plain C++ that compiles with g++, then hand off to /hls-architect for multi-stage HLS dataflow architecture.


Preamble — Verify Tooling + Capture Required Parameters

Step 0 — Run ./reference/setup.md in tooling-only mode

All required tooling (Vitis HLS, MATLAB, OpenCV) is verified by the ./reference/setup.md skill. At this point in the flow there is no design directory yet, so call ./reference/setup.md with mode=tooling-only — design discovery and build commands (Steps 2 & 3 of ./reference/setup.md) are skipped.

./reference/setup.md mode=tooling-only

The ./reference/setup.md skill will:

  • Source Vitis (and export $XILINX_VITIS) — Step 1
  • Detect & verify OpenCV install if the testbench will use cv::imread — Step 4
  • Locate MATLAB and export $MATLAB_BIN — Step 5

If ./reference/setup.md cannot resolve a tool (e.g. MATLAB not on PATH, OpenCV lib path missing), it prompts the user with AskUserQuestion. Do not proceed until `./reference/setup.md` reports all three checks passed (or marked N/A).

After ./reference/setup.md returns, the following env vars are guaranteed to be set:

Env varSet byUsed by
$XILINX_VITIS./reference/setup.md Step 1g++ compile commands in Step 2 & Step 4
$OPENCV_INCLUDE./reference/setup.md Step 4g++ -I flag for testbench compile
$OPENCV_LIB./reference/setup.md Step 4g++ -L flag for testbench compile
$MATLAB_BIN./reference/setup.md Step 5Step 0 — running the user's .m files

Downstream skills (/hls-architect, /hls-optimize, /csim, /csynth, /cosim) inherit this environment — never re-verify or re-source.

Capture pipeline parameters

Parse parameters from $ARGUMENTS:

Expected format:

/matlab-to-cpp <file.m> [part=<fpga-part>] [clock=<ns>] [throughput=<target>]

Examples:

/matlab-to-cpp rgbEdgeDetector.m part=xczu9eg-ffvb1156-2-e clock=3.3 throughput=4400fps
/matlab-to-cpp demosaic.m part=xczu9eg-ffvb1156-2-e clock=3.5
/matlab-to-cpp filter.m

Parse logic:

  1. Extract MATLAB file path (first non-key=value argument)
  2. Extract part=... → store as XPART
  3. Extract clock=... → store as CLOCK_NS
  4. Extract throughput=... → store as THROUGHPUT_TARGET

No silent defaults. If any of <matlab-file>, part=, clock=, or throughput= is missing from $ARGUMENTS, prompt the user with AskUserQuestion:

Missing argQuestion headerQuestion text
matlab file"MATLAB script""Which MATLAB script should I convert? (path to .m file)"
part="FPGA part""FPGA part to target? (e.g. xczu9eg-ffvb1156-2-e)"
clock="Clock period""Clock period in ns? (e.g. 3.3 for ~303 MHz)"
throughput="Throughput""Throughput target? (e.g. 4400 FPS, 500 Msps, 1 GFLOPS)"

Why no defaults: silent defaults (xczu9eg, 3.5 ns) used to mask user typos and propagate the wrong values into /hls-architect and /hls-optimize. The prompt forces an explicit choice and surfaces parsing failures immediately.

After all four are resolved, print confirmation:

─────────────────────────────────────────────────────
[matlab-to-cpp] Pipeline parameters
Source : <matlab-file>
Part : <XPART>
Clock : <CLOCK_NS> ns (≈ <MHz> MHz)
Throughput : <THROUGHPUT_TARGET>
─────────────────────────────────────────────────────

Flow Overview

Print this at the very start so the user can track progress throughout:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[matlab-to-cpp] Pipeline — <design_name>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 0 Run MATLAB simulation → save golden I/O
Step 0b Range instrumentation → sim-measured types
Step 1 Analyze MATLAB algorithm
Step 2 Generate refactor_1 (plain C++) + verify
Step 3 Generate refactor_2 (frame-based C++)
Step 4 Hand off to /hls-architect → /hls-optimize
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Re-print this overview after each step completes with a ✓ next to the completed step so the user always knows where the flow is.


Design Workspace

Before running Step 0, derive design_name from the MATLAB script filename (snake_case, no .m extension).

Call ./reference/design-layout.md to orient the workspace:

./reference/design-layout.md design_name=<name> stage=show

This prints the full expected directory tree without creating anything. Confirm the tree with the user, then proceed — each step calls ./reference/design-layout.md to create its directory before writing files.


Step 0 / 4 — Run MATLAB Simulation (Golden Reference)

─────────────────────────────────────────────────────
[matlab-to-cpp] Step 0 / 4 — Run MATLAB Simulation (Golden Reference)
─────────────────────────────────────────────────────

Before converting anything, run the MATLAB simulation to capture golden inputs and outputs. These are used in Step 2 to verify the generated C++.

Launch MATLAB CLI

Use $MATLAB_BIN — exported by ./reference/setup.md Step 5. Do NOT hardcode a path here; that breaks for any user other than the one whose path was baked in.

bash
"$MATLAB_BIN" -nodisplay -nodesktop

If $MATLAB_BIN is empty at this point, ./reference/setup.md mode=tooling-only was not run (or it failed) — go back and re-run it before continuing.

Run the Simulation

Once the MATLAB CLI is open, run the *_runme.m script in the design directory:

matlab
>> run('path/to/design_runme.m')

Important:

  • Run only the simulation section — do not run any MtoHDL Coder or code generation sections
  • If the runme script contains both, stop before the HDL/HLS coder calls
Save Inputs and Outputs

Save both the input data (stimulus) and output data (golden reference) so the C++ testbench can use the same files:

matlab
% Save input
fid = fopen('matlab_input.bin', 'wb');
fwrite(fid, input_array, 'uint8'); % match the actual data type
fclose(fid);
% Save golden output
fid = fopen('matlab_golden.bin', 'wb');
fwrite(fid, output_array, 'uint8');
fclose(fid);

Keep note of: output dimensions, data type, and border pixels that are undefined (e.g., warmup edges for filter kernels).

Write to golden/

Call ./reference/design-layout.md design_name=<name> stage=golden

Then copy into design_name/golden/:

  • All MATLAB source files (*.m) from the input design path
  • matlab_input.bin — saved stimulus
  • matlab_golden.bin — saved golden reference output

Print before proceeding:

─────────────────────────────────────────────────────
[matlab-to-cpp] Step 0 done — MATLAB Simulation
Input saved : golden/matlab_input.bin (<N> bytes, <dtype>)
Output saved : golden/matlab_golden.bin (<N> bytes, <dtype>)
Dimensions : <ROWS × COLS or signal length>
Border/warmup: <KSIZE/2 rows+cols invalid / N/A>
─────────────────────────────────────────────────────
✓ Step 0 Run MATLAB simulation → save golden I/O
Step 0b Range instrumentation → sim-measured types ← NEXT
Step 1 Analyze MATLAB algorithm
Step 2 Generate refactor_1 (plain C++) + verify
Step 3 Generate refactor_2 (frame-based C++)
Step 4 Hand off to /hls-architect → /hls-optimize

Step 0b — Range Instrumentation

─────────────────────────────────────────────────────
[matlab-to-cpp] Step 0b — Range Instrumentation
0b.0 Detect design type (A: script / B: function-based)
0b.1 Generate instrumented MATLAB files
0b.2 Re-run MATLAB, collect RANGE lines
0b.2b Precision sweep — measure F end-to-end vs golden
0b.3 Build range table (filter constants/masks)
0b.4 Derive W and I for each variable
0b.4b Select Q and O modes (closest to MATLAB double)
0b.4c Report quantization error (from the 0b.2b measurement)
0b.4d Size fixed-point multiply intermediates
0b.5 Present table → user accept / refine loop
─────────────────────────────────────────────────────

Capture min/max of every intermediate variable from the MATLAB simulation. This drives exact-bitwidth type selection in Step 2 — tight widths reduce area and improve achievable II. Without this, type selection falls back to conservative static analysis.

0. Detect design type

Examine the design directory:

  • Type A — script-based: the top-level runme calls no sub-function .m files; all computation is inline. The MATLAB who command can see all variables after the script runs.
  • Type B — function-based: the design has multiple .m files that start with the function keyword. Sub-function internals are invisible to who — only the function's return values appear in the caller's workspace. These require per-function instrumentation.

Detection rule: scan the design directory for .m files. If more than one file begins with function (excluding the runme/tb scripts), it is Type B.

1. Generate instrumented MATLAB files
Type A — append snippet to runme

Add this block to the end of the *_runme.m script, after the main algorithm has already executed. Do not modify the algorithm itself.

matlab
% --- Range instrumentation — append after main algorithm ---
fprintf('\n=== RANGE INSTRUMENTATION ===\n');
vars = who;
for k = 1:length(vars)
v = eval(vars{k});
if isnumeric(v) && ~isempty(v) && numel(v) > 1
vmin = double(min(v(:)));
vmax = double(max(v(:)));
is_int = all(v(:) == floor(v(:)));
fprintf('RANGE %-30s min=%12.4f max=%12.4f integer=%d\n', ...
vars{k}, vmin, vmax, double(is_int));
end
end
fprintf('=== END RANGE INSTRUMENTATION ===\n');
Type B — auto-generate instrumented sub-functions

Use the two scripts shipped with this repo under ./hls-scripts/:

bash
SCRIPTS_DIR="./hls-scripts"

Both gen_all_instr.py and gen_matlab_instr.py ship with the repo — no external download required.

Step 1: Generate `*_instr.m` for every sub-function:

bash
python3 $SCRIPTS_DIR/gen_all_instr.py --dir <design_dir>

This scans the design directory, finds all files starting with function, skips *_instr, *_runme, *_tb, *_range, *_init, and generates <name>_instr.m for each. The prefix embedded in every RANGE line equals the filename stem (e.g., hb2_fir_i.m → prefix hb2_fir_i).

Print the summary output from gen_all_instr.py — it lists every generated file and its tracked variable count.

Step 2: Create or update an instrumented runner.

Create <design_name>_full_instr_runme.m in the design directory that:

  1. Calls clear functions at the top to reset all persistent variables
  2. Calls the *_instr versions of every sub-function (not the originals)
  3. Uses the same stimulus and parameters as the original runme
  4. Prints any top-level coefficient/LUT ranges directly via fprintf('RANGE ...') before the pipeline loop

The RANGE lines are emitted by each *_instr.m function automatically at the end of their execution — no additional snippet is needed in the runner.

Note on loop-internal constants: gen_all_instr.py tracks ALL named assignments inside the outer loop, including constants like bit_start = 21 or offset = fi(1025,...). These will appear in the RANGE output with trivial ranges (e.g., [21,21]). Ignore them when building the type table — they are not signal-path variables.
Note on output_direct temps: assignments like cout(i) = expr_with_no_named_intermediate are captured via injected temp variables named rng_<array>_N. These appear as RANGE prefix_rng_<array>_N and represent the actual output signal value — keep them in the type table.

This is the start of the file. Read the full SKILL.md on GitHub.

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

Popularity

7-day trend score
0

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
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/xilinx/ross-ai-assistant/hls-matlab-to-cpp/badge)](https://verified-skill.com/skills/xilinx/ross-ai-assistant/hls-matlab-to-cpp)

Something wrong with this skill or its page? Tell us.