Skip to content

Commit

Permalink
[docs][runtime] Update docs and add csyn support to Vitis HLS (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
chhzh123 authored Sep 29, 2024
1 parent febe0a1 commit b1f6772
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 81 deletions.
26 changes: 19 additions & 7 deletions allo/backend/hls.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,13 @@ def __init__(
copy_build_files(self.top_func_name, project, mode, platform=platform)
copy_ext_libs(ext_libs, project)
if self.platform == "vitis_hls":
assert self.mode in {"csim", "sw_emu", "hw_emu", "hw"}, "Invalid mode"
assert self.mode in {
"csim",
"csyn",
"sw_emu",
"hw_emu",
"hw",
}, "Invalid mode"
assert (
self.top_func_name != "kernel"
), "kernel is a reserved keyword for vitis_hls"
Expand Down Expand Up @@ -314,9 +320,7 @@ def __repr__(self):

def __call__(self, *args, shell=True):
if self.platform == "vivado_hls":
assert (
os.system(f"which {self.platform} >> /dev/null") == 0
), f"cannot find {self.platform} on system path"
assert is_available("vivado_hls"), "vivado_hls is not available"
ver = run_process("g++ --version", r"\d+\.\d+\.\d+")[0].split(".")
assert (
int(ver[0]) * 10 + int(ver[1]) >= 48
Expand Down Expand Up @@ -351,9 +355,7 @@ def __call__(self, *args, shell=True):
else:
raise RuntimeError(f"{self.platform} does not support {self.mode} mode")
elif self.platform == "vitis_hls":
assert (
os.system(f"which {self.platform} >> /dev/null") == 0
), f"cannot find {self.platform} on system path"
assert is_available("vitis_hls"), "vitis_hls is not available"
if self.mode == "csim":
cwd = os.getcwd()
mod = IPModule(
Expand All @@ -367,6 +369,16 @@ def __call__(self, *args, shell=True):
)
mod(*args)
return
if self.mode == "csyn":
cmd = f"cd {self.project}; vitis_hls -f run.tcl"
print(
f"[{time.strftime('%H:%M:%S', time.gmtime())}] Begin synthesizing project ..."
)
if shell:
subprocess.Popen(cmd, shell=True).wait()
else:
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).wait()
return
assert "XDEVICE" in os.environ, "Please set XDEVICE in your environment"
cmd = f"cd {self.project}; make run TARGET={self.mode} PLATFORM=$XDEVICE"
print(cmd)
Expand Down
4 changes: 3 additions & 1 deletion allo/backend/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,9 @@ def parse_xml(path, prod_name, top="top", print_flag=False):
est_resources = area_estimate["Resources"]
avail_resources = area_estimate["AvailableResources"]
resources = {}
for name in ("BRAM_18K", "DSP48E", "FF", "LUT"):
for name in ("BRAM_18K", "DSP48E", "DSP", "FF", "LUT", "URAM"):
if name not in est_resources:
continue
item = [est_resources[name], avail_resources[name]]
item.append(f"{round(int(item[0]) / int(item[1]) * 100)}%")
resources[name] = item.copy()
Expand Down
8 changes: 4 additions & 4 deletions allo/harness/vitis/run.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ add_files kernel.cpp
add_files -tb host.cpp -cflags "-std=gnu++0x"

open_solution "solution1"
# Use Zynq device
set_part {xc7z020clg484-1}
# Target device is Alveo U280
set_part {xcu280-fsvh2892-2L-e}

# Target clock period is 10ns
create_clock -period 10
# Target frequency is 300 MHz
create_clock -period 3.33

# Directives

Expand Down
8 changes: 4 additions & 4 deletions docs/source/developer/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Basically, the development workflow is as follows:
3. Commit the changes to your *local* branch (``git commit -m "commit message"``)
4. Push the changes to your *fork* (``git push origin <branch_name>``)
5. Make sure your changes do not break the existing facilities, see `Integration Tests <#integration-tests>`_ for more details
6. Create a `PR <https://github.com/cornell-zhang/allo/pulls>`_ from your fork to the ``main`` branch of the Allo repository (see `here <https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork>`_ for more details)
6. Create a `Pull Request (PR) <https://github.com/cornell-zhang/allo/pulls>`_ from your fork to the ``main`` branch of the Allo repository (see `here <https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork>`_ for more details)
7. Wait for the PR to be reviewed
8. If there are any changes requested, make the changes and push to your fork
9. Once the PR is approved, it will be merged into the ``main`` branch
Expand All @@ -77,12 +77,12 @@ make sure you have passed the tests locally before creating a PR or pushing to y
There are several tests for our project:

1. **License header check**: make sure all the source files have the license header, which is important for open source projects.
2. **Code style check**: make sure the code style is consistent with the `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ standard. We use ``black`` for Python formatting, which should has been installed in your environment during the setup. ``clang-format`` is used for C/C++ formatting.
2. **Code style check**: make sure the Python code style is consistent with the `PEP8 <https://www.python.org/dev/peps/pep-0008/>`_ standard. We use ``black`` for Python formatting, which should has been installed in your environment during the setup. For the MLIR part, we use ``clang-format`` for C/C++ formatting.
3. **Linting check**: make sure the code is `linted <https://www.perforce.com/blog/qac/what-lint-code-and-what-linting-and-why-linting-important>`_ correctly. We use ``pylint`` for Python linting, which should also been installed during the setup.
4. **Unit tests**: make sure the changes will not break the existing facilities. We use ``pytest`` for Python unit tests, and the test cases are under the ``tests`` folder.

If you are making changes to the code, please make sure to run those tests before pushing to your fork.
To run the tests, you can run the following command from the root of the repository:
If you are making changes to the code, please make sure to run those tests and checking before pushing to your fork.
To run the format checker, you can execute the following command from the root of the repository:

.. code-block:: bash
Expand Down
8 changes: 4 additions & 4 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ Allo is an Accelerator Design Language (ADL) and compiler that facilitates the c

.. toctree::
:maxdepth: 1
:caption: Getting Started
:caption: **Getting Started**

setup/index.rst


.. toctree::
:maxdepth: 1
:caption: Tutorials
:caption: **Tutorials**

gallery/tutorial_01_get_started.rst
gallery/tutorial_02_vhls.rst


.. toctree::
:maxdepth: 1
:caption: Developer Guide
:caption: **Developer Guide**

developer/index.rst
gallery/developer_01_ir_builder.rst
Expand All @@ -51,6 +51,6 @@ Allo is an Accelerator Design Language (ADL) and compiler that facilitates the c

.. toctree::
:maxdepth: 1
:caption: Reference
:caption: **Reference**

genindex
2 changes: 1 addition & 1 deletion docs/source/setup/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ We also provide a script to set up the backend LLVM compiler. You can simply run

.. code-block:: console
$ source /work/shared/common/allo/setup-py312.sh
$ source /work/shared/common/allo/setup-llvm19.sh
.. note::

Expand Down
10 changes: 5 additions & 5 deletions tutorials/developer_01_ir_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# leverage the `parsing <https://en.wikipedia.org/wiki/Parsing>`_ technique to
# translate the Python code to an MLIR program. Therefore, the first
# step is to parse the Python code to the
# `AST <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`_ representation.
# `Abstract Syntax Tree (AST) <https://en.wikipedia.org/wiki/Abstract_syntax_tree>`_ representation.

M, N = 1024, 1024

Expand Down Expand Up @@ -69,7 +69,7 @@ def matrix_add(A: int32[M, N]) -> int32[M, N]:
# We also wrap the above functions in ``allo.customize``, you can
# directly call ``s = allo.customize(matrix_add, verbose=True)`` to obtain
# the AST of the function. The entry point of the ``customize`` function is
# located in `allo/customize.py <https://github.com/cornell-zhang/allo/blob/3cd1680f929f84e88bd2bbff4909bf13d95696f3/allo/customize.py#L339>`_.
# located in `allo/customize.py <https://github.com/cornell-zhang/allo/blob/main/allo/customize.py>`_.

##############################################################################
# Traverse the AST
Expand Down Expand Up @@ -170,7 +170,7 @@ def matrix_add(A: int32[M, N]) -> int32[M, N]:
# support different loop structures, so we need to further dispatch the ``For`` node to the corresponding
# builder function. For example, here we use ``allo.grid``, so it will be dispatched to ``build_grid_for``.
#
# We provide some helper functions in ``allo/ir/transform.py`` to make the IR creation easier.
# We provide some helper functions in `allo/ir/transform.py <https://github.com/cornell-zhang/allo/blob/main/allo/ir/transform.py>`_ to make the IR creation easier.
# In this case, we can just call ``build_for_loops`` and pass in the bounds and the names of the loops
# to create a loop nest.
# Before building the loop body, we need to update the insertion point:
Expand All @@ -188,9 +188,9 @@ def matrix_add(A: int32[M, N]) -> int32[M, N]:
##############################################################################
# Other Nodes
# ^^^^^^^^^^^
# The build process is similar for other nodes, so I will not go into them one by one.
# The build process is similar for other nodes, so we will not go into them one by one.
# Please refer to the `source code <https://github.com/cornell-zhang/allo/blob/main/allo/ir/builder.py>`_ for more details.
# After building the IR, you can call ``s.module`` to see the effect.
#
# Most of the MLIR operations can be found on this `webpage <https://mlir.llvm.org/docs/Dialects/>`_, and now
# you can follow the definitions and add more amazing facilities to the new Allo frontend!
# you can follow the definitions and add more amazing facilities to the new Allo compiler!
19 changes: 18 additions & 1 deletion tutorials/developer_02_mlir.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
# The first line gives the error message and the exact location (line 8, column 3) of the error.
# Then we know that there is a problem in the return value of our MLIR code, which helps us debug the program.
#
# To further check what causes the error, we can print out the generic form of the MLIR program.

# %%
mod.operation.print(
large_elements_limit=2,
enable_debug_info=True,
pretty_debug_info=True,
print_generic_op_form=True,
use_local_scope=True,
)

# %%
# The generic form of the MLIR program is a more detailed representation of the MLIR program.
# However, if you see this form in your customized MLIR pass, it means your generated IR may not pass the MLIR verifier.

# We also wrap the LLVM execution engine in allo, so we can directly invoke it to execute the MLIR program.
# The ``LLVMMoudle`` class takes the MLIR module and the name of the top function as input.
# Then we can directly invoke the module with random inputs, and see if the result is correct.
Expand Down Expand Up @@ -142,7 +157,9 @@
#
# .. code-block::
#
# python3: llvm-project/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp:209: mlir::FailureOr<llvm::SmallVector<mlir::Operation*, 4> > linalgOpToLoopsImpl(mlir::PatternRewriter&, mlir::linalg::LinalgOp) [with LoopTy = mlir::AffineForOp]: Assertion `linalgOp.hasBufferSemantics() && "expected linalg op with buffer semantics"' failed.
# python3: llvm-project/mlir/lib/Dialect/Linalg/Transforms/Loops.cpp:209:
# mlir::FailureOr<llvm::SmallVector<mlir::Operation*, 4> > linalgOpToLoopsImpl(mlir::PatternRewriter&, mlir::linalg::LinalgOp)
# [with LoopTy = mlir::AffineForOp]: Assertion `linalgOp.hasBufferSemantics() && "expected linalg op with buffer semantics"' failed.

# %%
# Unfortunately, the program cannot be lowered to LLVM dialect, because we have not added
Expand Down
3 changes: 2 additions & 1 deletion tutorials/tutorial_01_get_started.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def gemm(A: int32[32, 32], B: int32[32, 32]) -> int32[32, 32]:
# directly feed them into the executable. Allo will automatically handle the
# input data and generate corresponding internal wrappers for LLVM to execute,
# but we still need to make sure the data types are consistent. By default,
# ``np.random.randint`` will generate np.int64 data type, while we use ``int32``
# ``np.random.randint`` will generate ``np.int64`` data type, while we use ``int32``
# when defining our kernel function, so we need to explicitly cast the data type
# to ``np.int32``.

Expand All @@ -184,3 +184,4 @@ def gemm(A: int32[32, 32], B: int32[32, 32]) -> int32[32, 32]:

golden_C = np.matmul(np_A, np_B)
np.testing.assert_allclose(np_C, golden_C, rtol=1e-5, atol=1e-5)
print("Results are correct!")
Loading

0 comments on commit b1f6772

Please sign in to comment.