Developer Guide

FPGA Optimization Guide for Intel® oneAPI Toolkits

ID 767853
Date 3/31/2023
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Memory Attributes

The following table lists attributes that allow fine-grained control on how you can implement a variable (usually an array) in on-chip memory. The attribute immediately precedes the variable declaration.

FPGA Memory Attributes

Attribute

Syntax

Description

bank_bits

[[intel::bank_bits(b0,b1,...,bn)]]

Specifies that the local memory addresses should use bits (b0,b1,...,bn) for bank selection, where, (b0,b1,...,bn) are indicated in terms of word-addressing and not byte-addressing. As a result, the number of banks is equal to 2<number of bank bits>. The bits of the local memory address not included in (b0,b1,...,bn) are used for word selection in each bank.

bankwidth

[[intel::bankwidth(N)]]

Specifies that the memory system implementing the local variable must have banks that are N bytes wide, where N is a power-of-2 integer value greater than zero.

doublepump

[[intel::doublepump]]

Specifies that the memory system implementing the local variable must operate at twice the clock frequency of the kernel accessing it. This allows twice as many memory accesses per kernel clock cycle but may reduce the maximum kernel clock frequency.

force_pow2_depth

[[intel::force_pow2_depth(N)]]

Specifies that the memory implementing the variable or array has a power-of-2 depth. This attribute is enabled if N is 1, and disabled if N is 0.

max_replicates

[[intel::max_replicates(N)]]

Specifies that the memory implementing the local variable or array has no more than the specified number of replicates to enable simultaneous reads from the datapath.

TIP:

For additional information, refer to the FPGA tutorial sample "Memory Attributes" listed in the Intel® oneAPI Samples Browser on Linux* or Windows*, or access the code sample on GitHub.

Struct Data Types and Memory Attributes

You can apply memory attributes to the member variables in a struct variable within the struct declaration. If you also apply memory attributes to the object instantiation of a struct variable, the attributes on the instantiation override the attributes from the declaration.

Consider the following code example where memory attributes are applied to both a declaration and instantiation:

struct State { [[intel::fpga_memory]] int array[100]; [[intel::fpga_register]] int reg[4]; }; cgh.single_task<class test>([=] { struct State S1; [[intel::fpga_memory]] struct State S2; // some uses });

In this example code, the compiler splits S1 into two variables, S1.array[100] (implemented in the memory) and S1.reg[4] (implemented in registers). However, the compiler ignores attributes applied at the struct declaration for object S2 and does not split it since the S2 object has the [[intel::fpga_memory]] attribute applied to it.