Vitis HLS Process Overview

Vitis HLS is project based. Each project holds one set of C code and can contain multiple solutions. Each solution can have different constraints and optimization directives. You can analyze and compare the results from each solution in the Vitis HLS GUI.

The following are the synthesis, analysis, and optimization steps in the typical design flow:

  1. Create a new Vitis HLS project.
  2. Verify the source code with C simulation.
  3. Run high-level synthesis to create RTL results.
  4. Analyze the results by examining latency, initiation interval (II), and throughput.
  5. Optimize and repeat as needed.
  6. Verify the results using C/RTL Co-simulation.

Vitis HLS implements the solution based on the default tool configuration, design constraints, and any optimization pragmas or directives you specify. You can use optimization directives to modify and control the implementation of the internal logic and I/O ports, overriding the default behaviors of the tool.

The C/C++ code is synthesized as follows:

  • Top-level function arguments synthesize into RTL I/O port interfaces automatically by Vitis HLS. As described in Managing Interface Synthesis, the default interfaces that the tool creates depends on the target flow, the data type and direction of the function argument, the default interface mode, and any user-specified INTERFACE pragmas or directives that manually define the interface.
  • Sub-functions of the top-level C/C++ function synthesize into blocks in the hierarchy of the RTL design.
    • The final RTL design includes a hierarchy of modules or entities that have a one-to-one correspondence with the original top-level C function hierarchy.
    • Vitis HLS automatically inlines sub-functions into higher level functions, or the top-level function as needed to improve performance.
    • You can disable automatic inlining by specifying the INLINE pragma to a sub-function, or using set_directive_inline, and setting it to OFF in your solution.
    • By default, each call of the C sub-function uses the same instance of the RTL module. However, you can implement multiple instances of the RTL module to improve performance by specifying the ALLOCATION pragma, or using the set_directive_allocation in your solution.
  • Loops in the C functions are kept rolled and are pipelined by default to improve performance.
    • The Vitis HLS tool will not unroll loops unless it improves the performance of the solution, like unrolling nested loops to pipeline the top-level loop. When loops are rolled, synthesis creates the logic for one iteration of the loop, and the RTL design executes this logic for each iteration of the loop in sequence. Unrolled loops let all iterations of the loop occur in parallel, but consume more device resources.
    • You can manually unroll loops using the UNROLL pragma, or the set_directive_unroll command.
    • Loops can also be pipelined, either with a finite-state machine fine-grain implementation (loop pipelining) or with a more coarse-grain handshake-based implementation (dataflow).
  • Arrays in the code are synthesized into block RAM, LUT RAM, or UltraRAM in the final FPGA design.
    • If the array is on the top-level function interface, high-level synthesis implements the array as ports with access to a block RAM outside the design.
    • You can reconfigure the type of memory used, or reconfigure read/write memory transfers using the ARRAY_PARTITION or ARRAY_RESHAPE pragmas, or the associated set_directive_array commands to change the default assignments.
IMPORTANT: In Vitis HLS, if you specify a pragma or directive in a particular scope (function/loop/region), then the default behavior of the tool as described above will be overridden by your pragma. In that case, default behaviors like auto-pipelining of loops with low iterations counts may not be applied if you have specified pragmas or configurations in the current scope.

After synthesis, you can analyze the results in the various reports produced to determine the quality of your results. After analyzing the results, you can create additional solutions for your project specifying different constraints and optimization directives, and synthesize and analyze those results. You can compare results between different solutions to see what has worked and what has not. You can repeat this process until the design has the desired performance characteristics. Using multiple solutions allows you to proceed with development while retaining prior solutions.