VFS Objects - 2025.1 English - UG1701

Embedded Design Development Using Vitis User Guide (UG1701)

Document ID
UG1701
Release Date
2025-07-16
Version
2025.1 English

VFS object classes are used to instantiate and control the simulation of AI Engine graphs and HLS kernels. You can instantiate a VFS simulation object using either aie_graph_handle = vfs.aieGraph(<arg>) or hls_kernel_handle = vfs.hlsKernel(<arg>). The VFS object is compiled and simulated with a <vfs_handle>.run method. This method checks the compilation status of the object and acts as an API to pass input and output to the object. The run method is described in Methods to Pass Inputs and Get Outputs with the Run API.

The instantiation argument can be provided as:

  1. Key-Value pairs
  2. Configuration file

Both initialization options share the following properties:

  • They create a vfsBuildDir under the component's work directory.
  • Both absolute and relative paths are accepted. The relative paths are relative to the location of the MATLAB or Python script.
  • All files and directories are checked for correctness.
  • An error is thrown if validation fails.

During test bench execution, VFS creates a vfs_work folder structure and compiles the design if required.

Passing Key Value Pairs

The key-value pairs method provides a flexible handling of the simulation objects, as the values can be defined or generated by the test bench. VFS uses these parameters to generate a configuration file and checks for a corresponding existing build. If there is no matching build, a new build is initiated.

The following is an example of an AIE Graph using key-value pairs:

# AIE Graph example using key-value pairs:
aie_graph = vfs.aieGraph(
  input_file: '<path_to_src>/front_ifft_with_twid.cpp',
  platform: '<path_to_platforms>/xilinx_vck190_base_202510_1.xpfm',
  include_paths: [
    '<path_to_src>',
    '<path_to_inc>',
    '<path_to_libraries>'
    ]
)

The following is an example of an HLS Kernel using key-value pairs:

# HLS Kernel example using key-value pairs:
hls_kernel = vfs.hlsKernel(
        part: 'xcvs1902-vsva2197-2MP-e-S',
        hls_function: '<top_function_name>',
        input_files: [
            '../prj/hls_src/ifft_transpose.cpp',
            '../prj/hls_src/ifft_transpose.h'
        ]
)

Details for Key-value pairs:

  • The part or platform is used to select the device. If not specified, the default is xcvs1902-vsva2197-2MP-e-S.
  • For AI Engine graphs:
    • input_file is a path to a .cpp top test bench that instantiates the graph and contains the main function.
    • A directory named input_file_hash is created.
  • For HLS kernels:
    • hls_function declares the kernel that is the top function.
    • A directory named top_function_hash is created
Table 1. Key-Value Pair Requirements
Key Applies to VFS object type Type Required Description
input_file aieGraph string Yes Point to the top test bench graph file.
input_files hlsKernel array (Python) or cell array (MATLAB) of string Yes Point to source files used by the HLS kernel.
hls_function hlsKernel string Yes Top function name of the HLS kernel.
include_paths aieGraph / hlsKernel array (Python) or cell array (MATLAB) of string No Path to include files.
part aieGraph / hlsKernel string No Select target device using part number. Default is xcvs1902-vsva2197-2MP-e-S.
platform aieGraph / hlsKernel string No Path to a platform .xpfm file.
Note: If this option is used, omit the part key-value pair.

Passing a Configuration File

The following example demonstrates how to use the configuration file when instantiating the simulation object. Compilation occurs the first time the object is created or if a dependent file is modified. When the test bench is re-run, it checks for any changes in source files or configuration file parameters and reconstructs the object with a new hash if necessary.

# AIE Graph example using config file:
myGraph = vfs.aieGraph(config_file = "<path_to_design>/my_config_file.cfg")
# HLS Kernel example using config file:
myKernel = vfs.hlsKernel(vfs_build_dir = "<path_to_design>/myBuildDir")

When using the configuration file, the following conditions apply:

  • The configuration file must be the only parameter specified
  • For AI Engine, a directory named input_file_hash is created
  • For HLS, a directory named top_function_hash is created

Example of a configuration file for a VFS graph object:

include = <path_to>/src
include = <path_to>/inc
input_files = <aie_graph_top>.cpp
part = xcvc1902-vsva2197-1LP-e-S
target = x86sim

Example of a configuration file for a VFS kernel object:

part = xcvc1902-vsva2197-1LP-e-S
[hls]
flow_target = vivado
package.output.format = ip_catalog
package.output.syn = false
syn.cflags = 
syn.file = <hls_kernel>.cpp
syn.top = <hls_kernel>

The following is an example of the vfs_work folder structure using the configuration file option:


vfs_work
  |-→ <name_from_cfg>_hash
        |-→ work (aie or hls work directory)
        |-→ <copy_of_config_file>
        |-→ vfsBuildDir
              |-→ libvfssim.so
              |-→ vfs_interface_spec.json

Methods to Pass Inputs and Get Outputs with the Run API

The simulation object produce outputs only when sufficient input data is provided. To help determine relevant input and output sizes, you can query an AI Engine graph object or HLS kernel for the expected input and output data size and types using the <vfs_object>.getInputSpec and <vfs_object>.getOutputSpec methods. The following example shows a query of the input specification of a graph object.

    Index        Name         DataType        Type        Size 
    _____    _____________    ________    ____________    _____

      1      "fir_sig_in0"    "cint16"    "iobuffer"      "256"
      2      "fir_sig_in1"    "cint16"    "iobuffer"      "256"
      3      "coeff[0]"       "int16"     "rtp(async)"    "16" 
      4      "coeff[1]"       "int16"     "rtp(async)"    "16" 

There are three methods available to pass the data.

The following table illustrates an HLS kernel with two input ports and two outputs as an example. Each input port requires 4 samples of int16 data, and the kernel produces two outputs of the same size.

Table 2. Comparing Input Methods
Method to pass data Example Comments
Each input separately
# Python example
import vfs
import varray as va
import numpy as np
in1 = va.array([0,1,2,3],va.int16)
in2 = va.array(np.array(range(4))+10,va.int16)
% MATLAB example
in1 = varray.int16([0:3]);
in2 = varray.int16([0:3]+10);
[out1, out2] = myKernel.run(in1, in2);
In this case, one input is used per port.
Note: If the input vector size is smaller than specified, the output is not produced until the next run provides sufficient input data to meet the graph or kernel specification. In this case, the output is an empty array.
Cell array in MATLAB or a list in Python
# Python example
in_list = [in1 in2]
out_list = myKernel.run(in_list)
% MATLAB example
in_cellarray = {in1, in2};
out_cellarray = myKernel.run(in_cellarray);
This case is suitable for kernels or graphs with numerous inputs or outputs, providing a compact style for managing the data.
Matrix
# Python example
in_matrix = va.array(np.matrix('0, 10; 1, 11; 2, 12; 3, 13',va.int16));
out_list = myKernel.run(in_matrix)
% MATLAB example
in_matrix = varray.int16([0, 10; 1, 11; 2, 12; 3, 13]);
[out1, out2] = myKernel.run(in_matrix);
For matrix inputs, the shape of the matrix must match the input specification. The columns of the matrix represent the ports.
Important: Only one input matrix is supported.
Note: The output format with this method is a list in Python or cell array in MATLAB. It is up to the user to reformat the output into a matrix if needed.