heterocl.dsl

heterocl.and_(*args)

Compute the logic AND between expressions.

heterocl.or_(*args)

Compute the logic OR between expressions.

heterocl.if_(cond)

Construct an IF branch.

heterocl.else_()

Construct an ELSE branch.

heterocl.elif_(cond)

Construct an ELIF branch.

heterocl.for_(begin, end[, step, name, …])

Construct a FOR loop.

heterocl.while_(cond)

Construct a WHILE loop.

heterocl.break_()

Construct a BREAK statement.

heterocl.def_(shapes[, dtypes, ret_dtype, …])

Define a HeteroCL function from a Python function.

heterocl.return_(val)

Return an expression within a function.

and_(*args)[source]

Compute the logic AND between expressions.

If there is only one argument, itself is returned.

Parameters

args (list of Expr) – A list of expression to be computed

Returns

Return type

Expr

Examples

A = hcl.placeholder((3,))
cond = hcl.and_(A[0] > 0, A[1] > 1, A[2] > 2)
or_(*args)[source]

Compute the logic OR between expressions.

If there is only one argument, itself is returned.

Parameters

args (list of Expr) – A list of expression to be computed

Returns

Return type

Expr

Examples

A = hcl.placeholder((3,))
cond = hcl.or_(A[0] > 0, A[1] > 1, A[2] > 2)
if_(cond)[source]

Construct an IF branch.

The usage is the same as Python if statement. Namely, a single if statement without the else branch is allowed. In addition, we cannot use else and elif without an if statement. Finally, an else statement must be preceded by either an if or elif statement.

Parameters

cond (Expr) – The condition of the if statement

Returns

Return type

None

Examples

def my_compute(x):
    with hcl.if_(A[x] < 3):
        # do something
    with hcl.elif_(A[x] < 6):
        # do something
    with hcl.else_():
        # do something
else_()[source]

Construct an ELSE branch.

Returns

Return type

None

See also

if_()

elif_(cond)[source]

Construct an ELIF branch.

Parameters

cond (Expr) – The condition of the branch

Returns

Return type

None

See also

if_()

for_(begin, end, step=1, name='i', dtype='int32', for_type='serial')[source]

Construct a FOR loop.

Create an imperative for loop based on the given bound and step. It is the same as the following Python code.

for i in range(begin, end, step):
    # do something

The bound and step can be negative values. In addition, begin is inclusive while end is exclusive.

Parameters
  • begin (Expr) – The starting bound of the loop

  • end (Expr) – The ending bound of the loop

  • step (Expr, optional) – The step of the loop

  • name (str, optional) – The name of the iteration variable

  • dtype (Type, optional) – The data type of the iteration variable

  • for_type (str, optional) – The type of the for loop

Returns

The iteration variable

Return type

Var

See also

break_()

Examples

# example 1 - basic usage
with hcl.for_(0, 5) as i:
    # i = [0, 1, 2, 3, 4]

# example 2 - negative step
with hcl.for_(5, 0, -1) as i:
    # i = [5, 4, 3, 2, 1]

# example 3 - larger step
with hcl.for_(0, 5, 2) as i:
    # i = [0, 2, 4]

# example 4 - arbitrary bound
with hcl.for_(-4, -8, -2) as i:
    # i = [-4, -6]
while_(cond)[source]

Construct a WHILE loop.

Parameters

cond (Expr) – The condition of the loop

Returns

Return type

None

See also

break_()

Examples

with hcl.while_(A[x] > 5):
    # do something
break_()[source]

Construct a BREAK statement.

This DSL can only be used inside a while loop or a for loop. Moreover, it is not allowed to have tracing statements after the break.

Returns

Return type

None

Examples

# example 1 - inside a for loop
with hcl.for_(0, 5) as i:
    with hcl.if_(A[i] > 5):
        hcl.break_()

# example 2 - inside a while loop
with hcl.while_(A[i] > 5):
    with hcl.if_(A[i] > 10):
        hcl.break_()
def_(shapes, dtypes=None, ret_dtype=None, name=None, arg_names=None)[source]

Define a HeteroCL function from a Python function.

This DSL is used as a Python decorator. The function defined with HeteroCL is not inlined by default. Users need to provide the shapes of the arguments, while the data types of the arguments and the returned data type are optional. This DSL helps make the algorithm more organized and could potentially reduce the memory usage by reusing the same functionality. Users can later on use compute primitives to decide whether to inline these functions or not.

After specifying a Python function to be a HeteroCL function, users can use the function just like using a Python function. We can also apply optimization primitives.

Parameters
  • shapes (list of tuple) – The shapes of the arguments

  • dtypes (list of Type, optional) – The data types of the argument

  • ret_dtype (Type, optional) – The data type of the returned value

  • name (str, optional) – The name of the function. By default, it is the same as the Python function

Returns

Return type

None

Examples

# example 1 - no return
A = hcl.placeholder((10,))
B = hcl.placeholder((10,))
x = hcl.placeholder(())

@hcl.def_([A.shape, B.shape, x.shape])
def update_B(A, B, x):
    with hcl.for_(0, 10) as i:
        B[i] = A[i] + x

# directly call the function
update_B(A, B, x)

# example 2 - with return value
@hcl.def_([(10,), (10,), ()])
def ret_add(A, B, x):
    hcl.return_(A[x] + B[x])

# use inside a compute API
A = hcl.placeholder((10,))
B = hcl.placeholder((10,))
C = hcl.compute((10,), lambda x: ret_add(A, B, x))
D = hcl.compute((10,), lambda x: ret_add(A, C, x))
return_(val)[source]

Return an expression within a function.

This DSL should be used within a function definition. The return type can only be an expression.

Parameters

val (Expr) – The returned expression

Returns

Return type

None

Examples

# example 1 - using with a compute API
A = hcl.placeholder((10,))

def compute_out(x):
    with hcl.if_(A[x]>0):
        hcl.return_(1)
    with hcl.else_():
        hcl.return_(0)

B = hcl.compute(A.shape, compute_out)

# example 2 - using with a HeteroCL function
A = hcl.placeholder((10,))

@hcl.def_([A.shape, ()])
def compute_out(A, x):
    with hcl.if_(A[x]>0):
        hcl.return_(1)
    with hcl.else_():
        hcl.return_(0)

B = hcl.compute(A.shape, lambda x: compute_out(A, x))