Skip to content

Commit

Permalink
[API][Backend] Streaming and OpenCL Backends (cornell-zhang#138)
Browse files Browse the repository at this point in the history
* add sdaccel, aocl for heterocl

* fpga

* Create codeanalys_openclc.cc

* Update target.py

* run

* can run successfully

* Create codegen_opencl.cc

* now

* all done

* Update codegen_sdaccel.cc

* Update codegen_sdaccel.cc

* 	modified:   python/heterocl/tvm/target.py

* 	new file:   samples/ppac/gemm/csrcPrint.py
	new file:   samples/ppac/gemm/data.py
	new file:   samples/ppac/gemm/gemm_ppac.py
	new file:   samples/ppac/gemm/headcode.txt
	new file:   samples/ppac/gemm/ppac_common.py
	new file:   tvm/src/codegen/build_ppac.cc
	new file:   tvm/src/codegen/codegen_rv64_ppac.cc
	new file:   tvm/src/codegen/codegen_rv64_ppac.h

* all

* remove tvm check code from kernel

* opencl-backend

* all

* fix ppac module build

* support ppac MVPb pragma

* fix ignoring ppac pragma in cpu backend

* opencl-backend

* aocl-backend

* move ppac codegen to ppac folder; fix argument name with merlinc analyser

* discard the new for-loop type; include ppac in hlib

* discard some previous changes

* Use int64_t as return type of GeMM on ppac

* [add] codegenc kernedef + stream init

* [add] var_shape_map

* [update] kerneldef struct shape

* [update] use noderef and restore

* [fix] return op

* [add] hcl device & kernelstmt printer

* [fix] def workaround

* [update] stream example

* [add] stream expr & stmt ir

* [fix] kernel arg location for stream

* opt1

* opencl-general

* new-version

* no bug

* a

* test+unroll+pipeline

* pragma

* new

* type has fixed

* new_test

* test_reorder_split_fuse

* target

* order

* simplified by rui

* analysis

* bug fixed

* [delete] all of the code about opencl

* [ADD] new opencl back-end including xilinx & intel

* fixed __local

* fixed data_type for xilinx opencl

* add makefile for SDAccel_runtime

* add the runtime for sdaccel

* create the sdaccel host

* fixed the indent problem partly

* test the zhang-05 server

* add indent to the host.cpp

* automatically generate makefile

* delete common folder from opencl

* add shmat to sdaccel runtime

* fixed bug for sdaccel runtime seg fault

* fixed the bug of host.cpp multiple

* fixed host.cpp multiple bug

* fixed endif for makefile

* modify sdaccel_sw_emu -> sdaccel_csim

* fix the __local and __global for intel opencl back-end

* Fix the arbitrary integer precision for aocl

* [add] ir visitor & functor for codegen

* [add] aocl stream codegen

* [add] aocl stream support

* [fix] aocl type conversion

* [fix] aocl channel syntax

* [add] sch.stream_to

* [fix] add stream annotation

* [add] host device codegen

* [add] stream ir mutator

* [Add] Interface prag,a for SDx sim

* [add] host xcel codegen

* [update] build interface

* [update] new build interface

* [fix] temp update

* [update] stream example

* [add] rocc-ppac sim

* [rm] submodule

* [update] rocc ppac hlib

* [add] unified sim & kernel updater

* re-organize build common util

* [update] stream in codegen c

* [update] codegen construct for streaming

* [update] code post-processing

* [fix] test cases

* [fix] python compatibility

* [update] future

* [fix] metaclass

* [fix] test import issue
  • Loading branch information
hecmay authored and seanlatias committed Dec 10, 2019
1 parent c124eb9 commit 2c75344
Show file tree
Hide file tree
Showing 142 changed files with 10,417 additions and 572 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ test: &test
key: v1.03-libhcl-
- run: make build-python
- run: pip install --user pytest
- run: pip install --user future
- run: python -m pytest tests
- run: pip install --user mxnet
- run: python -m pytest samples
Expand Down
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ tags
docs/source/samples
docs/source/tutorials
soda_*
*.cpp
*.h
out

# Downloaded files
Expand Down
11 changes: 11 additions & 0 deletions HISTORY
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### 2019-12-09
* fixed issue of zc706 simulation
* remove kernel-name variable allocation before KernelDef
* change multi-dimension array access to row-major single-dimension access
* create local buffer for each on-device variable
* updated the `KernelUpdater` class (using position index instead of name)
* added `stream_arg_pos` map in `CodeGenC` to facilitate codegen with streaming
* fixed test cases
* changed tvm `build` function to support legacy string type target
* fixed opencl aocl data type mismatching issue
* fixed kernel def data type conversion issue
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ build-tvm: build-pkgs

build-hcl: build-tvm
cd python; \
python setup.py install --user; \
python setup.py develop --user; \
cd ../hlib/python; \
python setup.py install --user;
python setup.py develop --user;

build-python:
cd python; \
python setup.py install --user; \
python setup.py develop --user; \
cd ../hlib/python; \
python setup.py install --user;
python setup.py develop --user;

clean:
rm -rf build
Expand Down
3 changes: 3 additions & 0 deletions Makefile.config
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ CMAKE_OK = no
# set whether to use vivado hls runtime
USE_VIVADO_HLS = 1

# set whether to use sdaccel opencl runtime
USE_SDACCEL_HLS = 1

# Specify current directory level with respect to CLAY_ROOT
ifndef LEVEL
LEVEL := .
Expand Down
11 changes: 11 additions & 0 deletions hlib/python/hlib/nn.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ def _pad(*indices):
return data[tuple(index_tuple)]
return hcl.compute(out_shape, _pad, name='pad')

def conv2d_nchw_imp(Input, Filter, Output, stride=[1,1], padding=[[0,0],[0,0]]):
with hcl.for_(0,Output.shape[0]) as n:
with hcl.for_(0,Output.shape[1]) as c:
with hcl.for_(0,Output.shape[2]) as h:
with hcl.for_(0,Output.shape[3]) as w:
partial = hcl.scalar(0)
with hcl.for_(0,Filter.shape[-2]) as x:
with hcl.for_(0,Filter.shape[-1]) as y:
partial.v += Input[n][c][h+x][w+y] * Filter[0][0][x][y]
Output[n,c,h,w] = partial

def conv2d_nchw(Input, Filter, name="conv2d", stride=[1,1], padding=[[0,0],[0,0]]):
out_dtype = Input.dtype
batch, in_channel, in_height, in_width = Input.shape
Expand Down
1 change: 1 addition & 0 deletions hlib/rocc-ppac
Submodule rocc-ppac added at 40d323
1 change: 1 addition & 0 deletions python/heterocl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .compute_api import *
from .dsl import *
from .types import *
from .devices import *
from .nparray import *
from .debug import hcl_excepthook
from .tvm.intrin import *
Expand Down
4 changes: 2 additions & 2 deletions python/heterocl/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def app2(A, B, C):
# execute f2
"""
# set the configurations
config.init_dtype = init_dtype
config.init_dtype = init_dtype
# initialize global variables
Schedule.stage_ops = []
Schedule.last_stages = OrderedSet([])
Expand Down Expand Up @@ -90,7 +90,7 @@ def placeholder(shape, name=None, dtype=None):
"""
name = util.get_name("placeholder", name)
dtype = util.get_dtype(dtype)

if shape == ():
return Scalar(tvm_api._Var(name, dtype))
tensor = Tensor(shape, dtype, name)
Expand Down
5 changes: 5 additions & 0 deletions python/heterocl/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ class TensorError(HCLError):
def __init__(self, msg):
HCLError.__init__(self, msg, "\33[1;31m[Tensor]\33[0m ")

class DeviceError(HCLError):
"""A subclass for specifying device related exception"""
def __init__(self, msg):
HCLError.__init__(self, msg, "\33[1;31m[Device]\33[0m ")

def hcl_excepthook(etype, value, tb):
"""Customized excepthook
Expand Down
278 changes: 278 additions & 0 deletions python/heterocl/devices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
"""Define HeteroCL device types"""
#pylint: disable=too-few-public-methods, too-many-return-statements
from .debug import DeviceError
from .tools import option_table, model_table
from future.utils import with_metaclass

class tooling(type):
def __getattr__(cls, key):
if key in option_table:
return cls(key, *option_table[key])
else: # unsupported device
raise DeviceError("not supported")

class tool(with_metaclass(tooling, object)):
"""The base class for all device tooling
mode (sim/impl) is decided by tool configuration
e.g. run sw emulation by passing gcc / vivado_hls arg
and actual impl by passing sdaccel / aocl arg
Parameters
----------
types: str
Device of device to place data
model: str
Model of device to place date
"""
def __init__(self, name, mode, kwargs):
self.name = name
self.mode = mode
self.options = kwargs

def __getattr__(self, entry):
return self.mapping[entry]

def __call__(self, mode, setting={}):
self.mode = mode
self.options = setting
return self

def __str__(self):
return str(self.name) + "-" + \
str(self.mode) + ":\n" + \
str(self.options)

def __repr__(self):
return str(self.name) + "-" + \
str(self.mode) + ":\n" + \
str(self.options)

tool_table = {
"aws_f1" : tool("sdaccel", *option_table["sdaccel"]),
"zc706" : tool("vivado_hls", *option_table["vivado_hls"]),
"ppac" : tool("rocket", *option_table["rocket"]),
"stratix10_sx": tool("aocl", *option_table["aocl"]),
"llvm" : tool("llvm", *option_table["llvm"])
}

class Device(object):
"""The base class for all device types
The default data placement is on CPU.
Parameters
----------
types: str
Device of device to place data
model: str
Model of device to place date
"""
def __init__(self, types, vendor,
model, **kwargs):
self.vendor = vendor
self.types = types
self.model = model
self.impls = {"lang": ""}
for key, value in kwargs.items():
self.impls[key] = value

def __getattr__(self, key):
""" device hierarchy """
return self.impls[key]

def set_lang(self, lang):
assert lang in \
["opencl", "hlsc", "c", "opengl", "merlinc", "cuda", "metal"], \
"unsupported lang sepc " + lang
self.impls["lang"] = lang
return self

class CPU(Device):
"""cpu device with different models"""
def __init__(self, vendor, model, **kwargs):
if vendor not in ["riscv", "arm", "intel", "sparc", "powerpc"]:
raise DeviceError(vendor + " not supported yet")
assert "cpu_" + model in model_table[vendor], \
model + " not supported yet"
super(CPU, self).__init__("CPU", vendor, model, **kwargs)
def __repr__(self):
return "cpu-" + self.vendor + "-" + str(self.model) + \
":" + self.impls["lang"]

class FPGA(Device):
"""fpga device with different models"""
def __init__(self, vendor, model, **kwargs):
if vendor not in ["xilinx", "intel"]:
raise DeviceError(vendor + " not supported yet")
assert "fpga_" + model in model_table[vendor], \
model + " not supported yet"
super(FPGA, self).__init__("FPGA", vendor, model, **kwargs)
def __repr__(self):
return "fpga-" + self.vendor + "-" + str(self.model) + \
":" + self.impls["lang"]

class GPU(Device):
"""gpu device with different models"""
def __init__(self, vendor, model, **kwargs):
if vendor not in ["nvidia", "amd"]:
raise DeviceError(vendor + " not supported yet")
assert "gpu_" + model in model_table[vendor], \
model + " not supported yet"
super(GPU, self).__init__("GPU", vendor, model, **kwargs)
def __repr__(self):
return "gpu-" + self.vendor + "-" + str(self.model) + \
":" + self.impls["lang"]

class PIM(Device):
"""cpu device with different models"""
def __init__(self, vendor, model, **kwargs):
if model not in ["ppac"]:
raise DeviceError(model + " not supported yet")
super(PIM, self).__init__("PIM", vendor, model, **kwargs)
def __repr__(self):
return "pim-" + str(self.model)

dev_table = {
"aws_f1" : [CPU("intel", "e5"), FPGA("xilinx", "xcvu19p")],
"zc706" : [CPU("arm", "a9"), FPGA("xilinx", "xc7z045")],
"rocc-ppac" : [CPU("riscv", "riscv"), PIM("ppac", "ppac")],
"stratix10_sx": [CPU("arm", "a53"), FPGA("intel", "stratix10_gx")]
}

class env(type):
"""The platform class for compute environment setups
serves as meta-class for attr getting
default platform: aws_f1, zynq, ppac
Parameters
----------
host: str
Device of device to place data
model: str
Model of device to place date
"""
def __getattr__(cls, key):
if key == "aws_f1":
devs = dev_table[key]
host = devs[0].set_lang("opencl")
xcel = devs[1].set_lang("hlsc")
elif key == "zc706":
devs = dev_table[key]
host = devs[0].set_lang("hlsc")
xcel = devs[1].set_lang("hlsc")
elif key == "llvm":
devs = None
host = None
xcel = None
elif key == "ppac":
devs = dev_table["rocc-ppac"]
host = devs[0].set_lang("c")
xcel = None
else: # unsupported device
raise DeviceError("not supported")
tool = tool_table[key]
return cls(key, devs, host, xcel, tool)

class platform(with_metaclass(env, object)):
def __init__(self, name, devs, host, xcel, tool):
self.name = name
self.devs = devs
self.host = host
self.xcel = xcel
self.tool = tool

if isinstance(host, CPU):
self.cpu = host
if isinstance(xcel, FPGA):
self.fpga = xcel
elif isinstance(xcel, PIM) and \
xcel.model == "ppac":
self.ppac = xcel

def __getattr__(self, key):
""" return tool options """
return self.tool.__getattr__(key)

def __call__(self, tooling=None):
if tooling: # check and update
assert isinstance(tooling, tool)
self.tool = tooling
return self

def __str__(self):
return str(self.name) + "(" + \
str(self.host) + " : " + \
str(self.xcel) + ")"

def __repr__(self):
return str(self.name) + "(" + \
str(self.host) + " : " + \
str(self.xcel) + ")"

def device_to_str(dtype):
"""Convert a device type to string format.
Parameters
----------
dtype : Device or str
The device type to be converted
Returns
-------
str
The converted device type in string format.
"""
if isinstance(dtype, Device):
if isinstance(dtype, CPU):
return "cpu_" + str(dtype.model)
elif isinstance(dtype, FPGA):
return "fpga_" + str(dtype.model)
else:
if not isinstance(dtype, str):
raise DeviceError("Unsupported device type format")
return dtype

def device_to_hcl(dtype):
"""Convert a device type to Heterocl type.
Parameters
----------
dtype : Device or str
The device type to be converted
Returns
-------
Device
"""
if isinstance(dtype, Device):
return dtype
elif isinstance(dtype, str):
device, model = dtype.split("_")
if device == "cpu":
return CPU(model)
elif device == "gpu":
return GPU(model)
elif device == "fpga":
return FPGA(model)
else:
raise DeviceError("Unrecognized device type")
else:
raise DeviceError("Unrecognized device type format")

def get_model(dtype):
"""Get the model of a given device type.
Parameters
----------
dtype : Device or str
The given device type
Returns
-------
str
"""
dtype = dtype_to_hcl(dtype)
return dtype.types, dtype.model

Loading

0 comments on commit 2c75344

Please sign in to comment.