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.

Workflow for Shared HLS Components#

  1. Generate the HDL. Run Hog/Do WORKFLOW on the HLS project to produce the VHDL/Verilog/IP catalog at the location declared by VHDL_OUTPUT / VERILOG_OUTPUT / IP_OUTPUT in hog.conf.

  2. Inspect and commit. The repository is now “dirty” because of the newly generated HDL files. Check the HLS reports (utilisation, timing) and, if the results are satisfactory, commit the generated HDL together with the corresponding hls_config.cfg and C/C++ source changes.

  3. Build the Vivado project. Run Hog/Do WORKFLOW on the Vivado project that consumes the committed HDL. Because the RTL is already version-controlled, the Vivado build is fully reproducible and Hog can compute a clean SHA / version for it.

This two-step flow guarantees the traceability of the Vivado build: every Vivado run synthesises a clean, committed snapshot of the HLS-generated RTL.

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 .src file: Hog automatically parses hls_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:

  1. Reads each [hls:<component>] section from hog.conf.

  2. Resolves the HLS_CONFIG path to an absolute file path.

  3. Parses hls_config.cfg and collects every existing file or directory referenced by key=value lines (e.g. syn.file, tb.file, paths in -I cflags). Directories are recursively expanded into their files.

  4. 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

CREATE (C)

Creates the Vitis Unified workspace under Projects/<project>/vitis_unified/ and adds an HLS component for each [hls:*] section.

WORKFLOW (W)

For each [hls:*]: runs C synthesis, packaging and (if requested in hls_config.cfg) implementation, then exports VHDL/Verilog/IP catalog to the source tree.

SIMULATION (S)

Runs the HLS simulations enabled in hog.conf (CSIM=true and/or COSIM=true).

VIEW (V)

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=true plus 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> (requires package.output.format=ip_catalog in hls_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 named timing_error.txt if the achieved period does not meet the requested clock; otherwise it is timing_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:

  1. Run ./Hog/Do CREATE <project> to create the Vitis Unified workspace under Projects/<project>/vitis_unified/.

  2. 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.

  3. 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.