Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DOC] Update documents for installation and tutorials (i.e., data placement and extern IP) #379

Open
wants to merge 7 commits into
base: tvm
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
sphinx_gallery_conf = {
'examples_dirs': ['../../samples', '../../tutorials'],
'gallery_dirs': ['samples', 'tutorials'],
'ignore_pattern': '(.*data\.py)|(.*merlinc\.py)|(example.*py)|(test.*py)|(__init__.py)|(.*golden.*py)|(.*_vhls\.py)',
'ignore_pattern': '(.*data\.py)|(.*merlinc\.py)|(example.*py)|(test.*py)|(__init__.py)|(.*golden.*py)|(.*_vhls\.py)|(.*stream\.py)|(.*_sdaccel\.py)|(.*withoutq.*)',
'filename_pattern': '(.*_main\.py)|(tutorial.*py)',
'within_subsection_order': FileNameSortKey,
'download_all_examples': False,
Expand Down
4 changes: 4 additions & 0 deletions docs/source/heterocl.api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ heterocl\.api
heterocl.lower
heterocl.build
heterocl.cast
heterocl.select
heterocl.print

.. autofunction:: heterocl.init
.. autofunction:: heterocl.placeholder
Expand All @@ -20,3 +22,5 @@ heterocl\.api
.. autofunction:: heterocl.lower
.. autofunction:: heterocl.build
.. autofunction:: heterocl.cast
.. autofunction:: heterocl.select
.. autofunction:: heterocl.print
38 changes: 38 additions & 0 deletions docs/source/install_from_prebuilt.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Insrall from Pre-built Images
=============================
With this method, you can easily deploy and try out HeteroCL. However, to use the latest features and patches,
please install from source.

Install with Conda
------------------
First install conda (Anaconda or miniconda) and create an empty virtual environment. It is recommended to install HeteroCL in a new conda env without any other pre-installed packages to avoid potential conflicts.

.. code:: bash

conda create --name hcl-env
conda activate hcl-env

After activating the conda environment, you can install the pre-built heterocl library and python packages.

.. code:: bash

conda install -c cornell-zhang heterocl


Install with Docker
-------------------
First make sure docker service is activated on your system by running the hello-world docker image example.

.. code:: bash

docker run hello-world

Then pull back the docker image from DockerHub, and run it using interactive mode. Conda virtual env is pre-installed in the docker image. After activating the conda env, you can use the HeteroCL package.

.. code:: bash

docker pull hecmay/heterocl:0.3
docker run -it hecmay/heterocl:0.3 bash

source /opt/conda/etc/profile.d/conda.sh
conda activate py36
38 changes: 38 additions & 0 deletions docs/source/install_from_src.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Build and Install from Source
=============================
To build and install HeteroCL from source, please follow the following steps.

1. Create a virtual environment with conda (e.g., Anaconda or miniconda)
2. Download the source code from GitHub. For developers, please **fork** from the repo instead.

.. code:: bash

git clone https://github.com/cornell-zhang/heterocl.git

3. (*Optional*) Specify the CMake and/or LLVM path in ``Makefile.config``. For instance

.. code::

# set your own path to llvm-config
LLVM_CONFIG = /path/to/llvm-config

4. Run `make` to build and install HeteroCL. Note that for Mac users, you need to make sure `cmake` and `wget` are installed before running this command. It is recommended to install these tools using conda with `conda install wget cmake -y`

.. code:: bash

make -j8

For Developers
--------------

1. Set the environment variable ``PYTHONPATH`` to reflect the modifications of Python files

.. code:: bash

export PYTHONPATH=$HCL_HOME/python:$HCL_HOME/hlib/python

2. Run `make` under ``tvm`` to reflect the modification of C source files

.. code:: bash

make -C tvm
20 changes: 5 additions & 15 deletions docs/source/installation.rst
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
Installation
============
To install HeteroCL, simply clone it from the GitHub.

.. code:: bash

git clone --recursive https://github.com/cornell-zhang/heterocl.git
To install HeteroCL, we provide two ways: you can either build from source or use-prebuilt images with
conda or docker.

After that, go to the downloaded directory and make it.

.. code:: bash
.. toctree::

make -j8

We highly recommend running HeteroCL with Python 3 since Python 2 will be deprecated in 2020.

Options
-------

1. You can set your own CMake or LLVM version by setting the PATH in ``Makefile.config``.
2. You can turn off the VHLS C simulation feature by setting ``USE_VIVADO_HLS`` to 0 in ``Makefile.config``.
install_from_src
install_from_prebuilt
13 changes: 13 additions & 0 deletions tutorials/test_tutorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,16 @@ def test_tutorial_08():
def test_tutorial_09():

import tutorial_09_stencil

def test_tutorial_10():

import tutorial_10_platform

def test_tutorial_11():

import tutorial_11_placement

def test_tutorial_12():

import tutorial_12_extern_ip

66 changes: 66 additions & 0 deletions tutorials/tutorial_10_platform.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Use HeteroCL Platform Features
=======================
**Author**: Hecmay

In this tutorial, we show how to use the pre-defined platforms and configure the corresponding
toolflows in HeteroCL. The platform class contains a pre-defined list of supported platforms (e.g.
`hcl.platform.aws_f1` equipped with one VU9P FPGA acceleration card and an Intel Xeon CPU). HeteroCL
allows users to add their own custom platforms with various accelerators. The platform information
along with data placement scheme will be used to generate target specific backend code.

"""
import numpy as np
import heterocl as hcl

##############################################################################
# Create a program in HeteroCL
# -------------------
# Here we use the stencil kernel from last tutorial to showcase how to use the platform
# feature to generate host and device code, and run the program in different modes (e.g.
# software simulation, co-simulation or bistream).

def jacobi(input_image):
def jacobi_kernel(y, x):
return (input_image[y+1, x-1] +
input_image[y , x ] +
input_image[y+1, x ] +
input_image[y+1, x+1] +
input_image[y+2, x ]) / 5

return hcl.compute(input_image.shape, jacobi_kernel, name="output")

dtype = hcl.Float()
input_image = hcl.placeholder((480, 640), name="input", dtype=dtype)
s = hcl.create_schedule([input_image], jacobi)

##############################################################################
# Use the pre-defined platform
# -----------------------
# Here we use the AWS F1 platform for demonstration. Users can configure the
# the toolflow used on the platform. The supported toolflows : "vitis" (Xilinx Vitis),
# sdsoc(Xilinx SDSoC), "aocl" (Intel AOCL) and "vivado_hls" (Vivado HLS).
# HeteroCL provides users with four tool modes to facilitate the development process:
# sw_sim, hw_sim, hw_exe and debug. HeteroCL will return the generated code (i.e. host and device code)
# in the debug mode, or the compiled function in the other modes. The compiled function is hooked
# with the hardware or software running in the background. Namely, you can invoke FPGA or other
# accelerators with the python compiled function returned HeteroCL. HeteroCL runtime will handle the
# the compilation and deployment process based on the platform information.

p = hcl.Platform.aws_f1
p.config(compiler="vitis", mode="debug")

##############################################################################
# Data Movement between Devices
# --------------------
# The whole HeteroCL program is palced on host by default (as you may notice,
# HeteroCL returns empty device code in debug mode if no data movement is specified).
# The .to API allows users to move data to different device, and HeteroCL will
# figure out the portiton of the program to be mapped to accelerator. For example,
# the input image is moved to device scope, and the stencil kernel is executed on
# the device before the output is moved to host.

tensor = jacobi.output
s.to(input_image, p.xcel)
s.to(tensor, p.host)
print(hcl.build(s, p))
69 changes: 69 additions & 0 deletions tutorials/tutorial_11_placement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Use the Data Placement and Streaming Feature
=======================
**Author**: Hecmay
In this tutorial, we show how to use the .to() APIs to offload specific
compute regions to FPGA.
"""
import os
import numpy as np
import heterocl as hcl

##############################################################################
# Create Kernel Function
# -------------------
# Create a program with HeteroCL, and apply schedule primitives to optimize
# the performance. Here we use the GEMM as an example:
m = 64
k = 64
n = 64
dtype = hcl.Int(32)

matrix_1 = hcl.placeholder((m, k), dtype=dtype)
matrix_2 = hcl.placeholder((k, n), dtype=dtype)

def kernel(matrix_1, matrix_2):
r = hcl.reduce_axis(0, k, 'k')
return hcl.compute((m, n),
lambda x, y: hcl.sum(matrix_1[x, r] * matrix_2[r, y],
axis=r, dtype=dtype),
dtype=dtype,
name="out_matrix")

s = hcl.create_schedule([matrix_1, matrix_2], kernel)

##############################################################################
# Move tensor to device
# -----------------------
# HeteroCL has many built-in Platforms (including aws_f1, zc706, stratix 10, e.t.c).
# Here we use the zc706 Platform as an example. The zc706 Platform is associated with
# Vivado HLS tool by default. By using .to() primitives, tensors will be moved into device
# scope, and all computations depending on these tensors will be performed on FPGA.
# Note that you also need to move the result tensor back to host.

target = hcl.Platform.xilinx_zc706
s.to([matrix_1, matrix_2], target.xcel)
s.to(kernel.out_matrix, target.host)

##############################################################################
# Run the Compilation
# --------------------
# Run the compilation: after you are done with optimization and compute offloading,
# you will get a compiled function from HeteroCL, and this function to can be used to
# process the input array passed from HeteroCL python interface. The input data will
# be passed to the accelerator function, and all the computations offloaded to FPGA
# will be executed by the HLS tools running under the hood.

if os.getenv("LOCAL_CI_TEST"):
target.config(compiler="vivado_hls", mode="csyn")
f = hcl.build(s, target)

hcl_m1 = hcl.asarray(np.random.randint(10, size=(m, k)), dtype=dtype)
hcl_m2 = hcl.asarray(np.random.randint(10, size=(k, n)), dtype=dtype)
hcl_m3 = hcl.asarray(np.zeros((m, n)), dtype=dtype)
f(hcl_m1, hcl_m2, hcl_m3)

else:
target.config(compiler="vivado_hls", mode="debug")
print(hcl.build(s, target))

77 changes: 77 additions & 0 deletions tutorials/tutorial_12_extern_ip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
Insert HLS IP into HeteroCL program
=======================
**Author**: Hecmay
In this tutorial, we show how to insert manually written HLS IP into HCL program
"""

import heterocl as hcl
import numpy as np
import numpy.testing as tst
import os

from hlib.op.extern import (
create_extern_module, register_extern_ip,
register_tensors, include_dependency)

##############################################################################
# Define HLS IP
# -------------------
# Define the HLS code that contains the function to be included in the HCL program. Here we use a vector add as an example.
vadd_hls_ip = """
void vadd(const float* in1, float* in2, int size) {
for (int j = 0; j < size; j++) {
#pragma HLS PIPELINE II=1
in2[j] = in1[j] + 1;
}
}
"""
with open("vadd.cpp", "w") as fp:
fp.write(vadd_hls_ip)

##############################################################################
# Register HLS IP
# -------------------
# Register the external HLS IP function in HCL. The registered HLS function will be used later to
@register_extern_ip(type="vhls")
def vadd_vhls_ip(op1, op2, size, name=None):
# define HLS function name
if name is None: name = "vadd"
# define a HCL stage and registers the input and output
# tensors that
with hcl.Stage("ExternModule.vadd") as Module:
register_tensors([op1, op2])
# define the function name and input arguments
Module.ext_ip_name = name
Module.inputs = [op1, op2, size]
# define the source code and dependency files (e.g., headers)
deps = os.path.dirname(os.path.abspath(__file__))
source = [ "vadd.cpp" ]
Module.source = include_dependency(source)
create_extern_module(Module, ip_type="HLS")

##############################################################################
# Define HCL program using external HLS function
# -----------------------
# We first define the placeholders as the inputs to our program. In the main function, we first call HLS IP function and then use imperative coding style to manipulate data returned from HLS IP.
dtype = hcl.Float(32)
hcl.init(dtype)
size = 1024
op1 = hcl.placeholder((size,), dtype=dtype, name="op1")
op2 = hcl.placeholder((size,), dtype=dtype, name="op2")
# call external HLS function inside HCL program
def math_func(op1, op2):
vadd_vhls_ip(op1, op2, size)
op2[0] += 1

# host-accelerator data placement
target = hcl.Platform.aws_f1
s = hcl.create_schedule([op1, op2], math_func)
s.to(op1, target.xcel)
s.to(op2, target.host)

# test ir correctness
target.config(compiler="vitis", mode="debug")
code = hcl.build(s, target)
assert "#pragma HLS PIPELINE II=1" in code
os.remove("vadd.cpp")
Loading