Offset and Modes of Operation - 2022.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-06-07
Version
2022.1 English
Important: In the Vitis kernel flow the default mode of operation is offset=slave and should not be changed.

The AXI4 Master interface has a read/write address channel that can be used to read/write specific addresses. By default the m_axi interface starts all read and write operations from the address 0x00000000. For example, given the following code, the design reads data from addresses 0x00000000 to 0x000000C7 (50 32-bit words, gives 200 bytes), which represents 50 address values. The design then writes data back to the same addresses.

#include <stdio.h>
#include <string.h>
 
void example(volatile int *a){
   
#pragma HLS INTERFACE mode=m_axi port=a depth=50
   
  int i;
  int buff[50];
   
  //memcpy creates a burst access to memory
  //multiple calls of memcpy cannot be pipelined and will be scheduled sequentially
  //memcpy requires a local buffer to store the results of the memory transaction
  memcpy(buff,(const int*)a,50*sizeof(int));
   
  for(i=0; i < 50; i++){
    buff[i] = buff[i] + 100;
  }
   
  memcpy((int *)a,buff,50*sizeof(int));
}

The tool provides the capability to let the base address be configured statically in the Vivado IP for instance, or dynamically by the application or another IP during run time.

The m_axi interface can be both a master initiating transactions, and also a slave interface that receives the data and sends acknowledgment. Depending on the mode specified with the offset option of the INTERFACE pragma, an HLS IP can use multiple approaches to set the base address.

Tip: The config_interface -m_axi_offset command provides a global setting for the offset, that can be overridden for specific m_axi interfaces using the INTERFACE pragma offset option.
  • Master Mode: When acting as a master interface with different offset options, the m_axi interface start address can be either hard-coded or set at run time.
    • offset=off: Vitis HLS sets a base address for the m_axi interface when the IP is used in the Vivado IP integrator tool. One disadvantage with this approach is that you cannot change the base address during run time. See Customizing AXI4 Master Interfaces in IP Integrator for setting the base address.
      The following example is synthesized with offset=off, the default for the Vivado IP flow.
      void example(volatile int *a){
      #pragma HLS INTERFACE m_axi depth=50 port=a offset=off
         
        int i;
        int buff[50];
         
        //memcpy creates a burst access to memory
        //multiple calls of memcpy cannot be pipelined and will be scheduled sequentially
        //memcpy requires a local buffer to store the results of the memory transaction
        memcpy(buff,(const int*)a,50*sizeof(int));
         
        for(i=0; i < 50; i++){
          buff[i] = buff[i] + 100;
        }
         
        memcpy((int *)a,buff,50*sizeof(int));
      }
    • offset=direct: Vitis HLS generates a port on the IP for setting the address. Note the addition of the a port as shown in the figure below. This lets you update the address at run time, so you can have one m_axi interface reading and writing different locations. For example, an HLS module that reads data from an ADC into RAM, and an HLS module that processes that data. Since you can change the address on the module, while one HLS module is processing the initial dataset the other module can be reading more data into different address.
      void example(volatile int *a){
      #pragma HLS INTERFACE m_axi depth=50 port=a offset=direct
      ...
      }
    Figure 1. offset=direct
  • Slave Mode: The slave mode for an interface is set with offset=slave. In this mode the IP will be controlled by the host application, or the micro-controller through the s_axilite interface. This is the default for the Vitis kernel flow, and can also be used in the Vivado IP flow. Here is the flow of operation:
    1. initially, the Host/CPU will start the IP or kernel using the block-level control protocol which is mapped to the s_axilite adapter.
    2. The host will send the scalars and address offsets for the m_axi interfaces through the s_axilite adapter.
    3. The m_axi adapter will read the start address from the s_axilite adapter and store it in a queue.
    4. The HLS design starts to read the data from the global memory.

As shown in the figure below, the HLS design will have both the s_axilite adapter for the base address, and the m_axi to perform read and write transfer to the global memory.

Figure 2. AXI Adapters in Slave Mode

Offset Rules

The following are rules associated with the offset option:

  • Fully Specified Offset: When the user explicitly sets the offset value the tool uses the specified settings. The user can also set different offset values for different m_axi interfaces in the design, and the tool will use the specified offsets.
    #pragma HLS INTERFACE s_axilite port=return
    #pragma HLS INTERFACE mode=m_axi bundle=BUS_A port=out offset=direct
    #pragma HLS INTERFACE mode=m_axi bundle=BUS_B port=in1 offset=slave
    #pragma HLS INTERFACE mode=m_axi bundle=BUS_C port=in2 offset=off
  • No Offset Specified: If there are no offsets specified in the INTERFACE pragma, the tool will defer to the setting specified by config_interface -m_axi_offset.
    Note: If the global m_axi_offset setting is specified, and the design has an s_axilite interface, the global setting is ignored and offset=slave is assumed.
    void top(int *a) {
    #pragma HLS interface mode=m_axi port=a
    #pragma HLS interface mode=s_axilite port=a
    }