Vitis Unified High-Level Synthesis (HLS)#
Hog supports the AMD Vitis Unified High-Level Synthesis flow, allowing you to generate VHDL/Verilog/IP from C/C++ sources. The exported RTL can then be integrated into a separate Vivado project, following the Workflow for Shared HLS Components.
The HLS flow is driven by the standard hls_config.cfg file produced and consumed by the AMD Vitis Unified IDE. Hog wraps the vitis Python API to drive C simulation, C synthesis, C/RTL co-simulation, packaging and implementation, and to collect the resulting reports and binary products into the bin/ folder of your repository.
Warning
Vitis Unified HLS support requires the vitis executable (Vitis Unified, 2023.2 or newer) to be available in PATH.
Project Layout#
A Vitis Unified HLS project is a standalone HLS project: hog.conf starts with # vitis_unified <version> and contains one or more [hls:<component>] sections (no Vivado synthesis is run from this project). The full per-section reference is in HLS Section.
When the generated RTL has to be consumed by a Vivado project, keep the two flows in separate Hog projects (within the same repository or in different ones — Hog does not require splitting them) and follow the workflow below.
Single Source of Truth: hls_config.cfg#
Each HLS component points at a single hls_config.cfg that fully describes it (top function, source files, testbench, clock, target part, packaging options, etc.). This file:
Is the standard configuration file used by the Vitis Unified GUI, so the same file can be edited interchangeably from the IDE or by hand.
Is version-controlled in your repository alongside the C/C++ sources.
Acts as the only source of truth for Hog. There is no need to duplicate the list of files in a
.srcfile: Hog automatically parseshls_config.cfg, discovers all referenced files and include directories, and tracks them in its versioning/SHA system.
Example hls_config.cfg:
part=xczu4cg-fbvb900-1-e
[hls]
flow_target=vivado
package.output.format=ip_catalog
package.output.syn=true
clock=40MHz
syn.top=iir_lp_filter
syn.cflags=-I src
tb.cflags=-I src -I sim/model
syn.file=src/iir_lp_filter.h
syn.file=src/iir_lp_filter.cpp
tb.file=sim/iir_lp_filter_tb.cpp
Note
Paths inside hls_config.cfg (for syn.file, tb.file, cosim.file, and -I directories in syn.cflags/tb.cflags) must be relative to the directory containing hls_config.cfg, exactly as the Vitis Unified GUI expects.
Automatic File Tracking#
When Hog scans your project (e.g. Hog/Do LIST, Hog/Do WORKFLOW, Hog/Do VIEW), it:
Reads each
[hls:<component>]section fromhog.conf.Resolves the
HLS_CONFIGpath to an absolute file path.Parses
hls_config.cfgand collects every existing file or directory referenced bykey=valuelines (e.g.syn.file,tb.file, paths in-Icflags). Directories are recursively expanded into their files.Adds the cfg file itself plus all expanded files to a synthetic library named
<component>.src, used for SHA computation and dirty-flag detection.
The list of auto-discovered files is printed to the log as a tree, for example:
INFO : HLS component 'iir_lp_filter' (from hog.conf): 7 file(s) tracked
hog.conf [hls:iir_lp_filter] (auto-discovered)
├── example_vitis_unified_hls/hls/iir_lp_filter/hls_config.cfg
Inside hls_config.cfg (HLS auto-expand):
├── src/iir_lp_filter.h
├── src/iir_lp_filter.cpp
├── sim/iir_lp_filter_tb.cpp
├── sim/model/x1q.txt
└── sim/model/y1q_n8.txt
Any change to the cfg or to one of the discovered files marks the project as dirty, exactly like a regular .src file would.
Configuring an HLS Component in hog.conf#
Each HLS component is declared with a section of the form [hls:<component_name>]. The section is documented in detail in the HLS Section of the hog.conf reference. A minimal example is:
# vitis_unified 2024.2
[main]
PART=xczu4cg-fbvb900-1-e
[hls:my_hls_component]
HLS_CONFIG=my_project/hls/my_hls_component/hls_config.cfg
VHDL_OUTPUT=my_project/hls/my_hls_component/outputs/vhdl # omit or comment out to skip export
VERILOG_OUTPUT=my_project/hls/my_hls_component/outputs/verilog # omit or comment out to skip export
IP_OUTPUT=my_project/hls/my_hls_component/outputs/ip_catalog # use together with `package.output.format=ip_catalog` in `hls_config.cfg`. Omit or comment out to skip export
CSIM=true
COSIM=true
You can declare as many [hls:*] sections as needed. Each is built independently and produces its own per-component output folder.
Running the HLS Flow#
The HLS flow is driven through the standard Hog/Do directives:
Directive |
Behaviour for HLS components |
|---|---|
|
Creates the Vitis Unified workspace under |
|
For each |
|
Runs the HLS simulations enabled in |
|
Prints the auto-discovered HLS file tree for each component, alongside the regular list-file tree. |
Selecting Specific HLS Simulations#
Hog/Do SIMULATION accepts the standard -simset option to limit which simulations are run. For HLS, the simset name follows the <type>:<component> convention:
csim:<component>— only the C simulation of<component>cosim:<component>— only the C/RTL co-simulation of<component>(automatically triggers C synthesis if not already done)
Examples:
./Hog/Do SIMULATION my_project # all enabled HLS simulations
./Hog/Do SIMULATION my_project -simset csim:iir_lp_filter # only CSIM for iir_lp_filter
./Hog/Do SIMULATION my_project -simset cosim:iir_lp_filter # only COSIM for iir_lp_filter
If a simulation is requested for a component for which it is not enabled in hog.conf, Hog will run it anyway and emit a warning suggesting to set CSIM=true / COSIM=true in the corresponding [hls:*] section.
Granular Flow Control#
Within hls_config.cfg the standard Vitis keys control which flow steps are run:
C simulation →
csim.*C synthesis →
syn.*Co-simulation →
cosim.*Packaging →
package.*Implementation →
package.output.syn=trueplus the implementation directives (RTL synthesis and place & route inside Vitis HLS).
The HLS exports done after synthesis are controlled by Hog through hog.conf:
VHDL_OUTPUT=<dir>— copy the generated VHDL into<dir>(relative to the repo root). Comment out to skip.VERILOG_OUTPUT=<dir>— copy the generated Verilog into<dir>.IP_OUTPUT=<dir>— copy the generated IP catalog ZIP into<dir>(requirespackage.output.format=ip_cataloginhls_config.cfg).
Output Layout in bin/#
For each successful build, Hog collects the HLS reports and summary files into the bin/ folder using the following layout:
bin/<project>-<describe>/
└── <component>/
├── utilization.txt
├── timing_ok.txt # or timing_error.txt if timing failed
└── reports/... # raw HLS XML/HTML reports
Each component always has its own subfolder, even if there is only one HLS component in the project. This guarantees a uniform layout regardless of how many components are added later.
Markdown Release Notes#
Just like for Vivado projects, Hog generates two Markdown files per HLS component:
utilization.txt— resource utilisation table for both Synthesis and Implementation sections.timing_ok.txt/timing_error.txt— clock period, achieved frequency and slack. The file is namedtiming_error.txtif the achieved period does not meet the requested clock; otherwise it istiming_ok.txt.
These files are picked up automatically by the GitLab/GitHub release-notes assembly (see Hog-CI Results) and are concatenated into the final release notes alongside the corresponding Vivado entries.
Tip
Because Hog uses the same timing_ok.txt / timing_error.txt naming convention as for Vivado, an HLS component whose timing is not met can fail the CI pipeline through the standard HOG_FAIL_TIMING mechanism, exactly like a Vivado project.
Per-Component Badges#
For CI, Hog generates one GitLab badge per HLS component (not one per project) summarizing resource utilisation and timing closure (OK green / FAILED red), with the component identified on the badge together with an HLS version label.
To select an HLS component for badges, add an entry of the form hls:<component_name> to HOG_BADGE_PROJECTS, where <component_name> is the same name as in the hog.conf section header [hls:<component_name>]. Example: for [hls:iir_lp_filter], use hls:iir_lp_filter.
Where to set HOG_BADGE_PROJECTS and how to combine HLS entries with Vivado project names is described in GitLab badges with resource utilisation and timing.
Editing in the Vitis Unified GUI#
The hls_config.cfg referenced from hog.conf is the same file the Vitis Unified GUI uses. You can:
Run
./Hog/Do CREATE <project>to create the Vitis Unified workspace underProjects/<project>/vitis_unified/.Open the workspace in the Vitis Unified IDE. The HLS components are imported referring directly to the source-tree
hls_config.cfg, so any edit done in the GUI (adding files, changing top, modifying clock, etc.) is persisted in the version-controlled file.Re-run
./Hog/Do WORKFLOW <project>from the command line to regenerate the bin folder with the updated configuration.
Complete Example#
The Hog example repository contains a ready-to-build HLS example:
example_vitis_unified_hls/
├── hls/
│ └── iir_lp_filter/
│ ├── hls_config.cfg
│ ├── src/
│ │ ├── iir_lp_filter.cpp
│ │ └── iir_lp_filter.h
│ └── sim/
│ ├── iir_lp_filter_tb.cpp
│ └── model/
│ ├── x1q.txt
│ └── y1q_n8.txt
└── ...
Top/example_vitis_unified_hls/
├── hog.conf
└── gitlab-ci.yml
To build it:
./Hog/Do CREATE example_vitis_unified_hls
./Hog/Do WORKFLOW example_vitis_unified_hls
./Hog/Do SIMULATION example_vitis_unified_hls
The build will produce bin/example_vitis_unified_hls-<describe>/iir_lp_filter/utilization.txt and timing_ok.txt/timing_error.txt, plus the exported VHDL/Verilog under the paths declared by VHDL_OUTPUT / VERILOG_OUTPUT.