Skip to content

Commit

Permalink
Fix minor programming guide bugs, add programming guide lit tests to …
Browse files Browse the repository at this point in the history
…CI workflows (#1509)
  • Loading branch information
hunhoffe authored May 28, 2024
1 parent b693d4e commit c9046f7
Show file tree
Hide file tree
Showing 39 changed files with 489 additions and 77 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/buildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ jobs:
ninja check-aie
ninja check-tutorials
ninja check-reference-designs
ninja check-programming-guide
# Build the repo test target in release mode to build and test.
- name: Build and test (Release)
Expand Down Expand Up @@ -165,3 +166,4 @@ jobs:
ninja check-aie
ninja check-tutorials
ninja check-reference-designs
ninja check-programming-guide
1 change: 1 addition & 0 deletions .github/workflows/buildAndTestMulti.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,5 @@ jobs:
ninja check-aie
ninja check-tutorials
ninja check-reference-designs
ninja check-programming-guide
fi
2 changes: 2 additions & 0 deletions .github/workflows/buildAndTestPythons.yml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ jobs:
ninja check-aie
ninja check-tutorials
ninja check-reference-designs
ninja check-programming-guide
# Build the repo test target in release mode to build and test.
- name: Build and test (Release)
Expand Down Expand Up @@ -164,3 +165,4 @@ jobs:
ninja check-aie
ninja check-tutorials
ninja check-reference-designs
ninja check-programming-guide
1 change: 1 addition & 0 deletions .github/workflows/buildAndTestRyzenAI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,6 @@ jobs:
ninja install
ninja check-reference-designs
ninja check-programming-guide
popd
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

![](https://mlir.llvm.org//mlir-logo.png)

This repository contains an [MLIR-based](https://mlir.llvm.org/) toolchain for AI Engine-enabled devices, such as [AMD Ryzen™ AI](https://www.amd.com/en/products/ryzen-ai) and [Versal™](https://www.xilinx.com/products/technology/ai-engine.html). This repository can be used to generate low-level configurations for the AI Engine portion of these devices. AI Engines are organized as a spatial array of tiles, where each tile contains AI Engine cores and/or memories. The spatial array is connected by stream switches that can be configured to route data between AI Engine tiles scheduled by their programmable Data Movement Accelerators (DMAs). This repository contains MLIR representations, with multiple levels of abstraction, to target AI Engine devices. This enables compilers and developers to program AI Engine cores, as well as describe data movements and array connectivity. A Python API is made available as a convenient interface for generating MLIR design descriptions. Backend code generation is also included, targeting the [aie-rt](https://github.com/Xilinx/aie-rt/tree/main-aie) library. This toolchain uses the AI Engine compiler tool which is part of the AMD Vitis™ software installation: these tools require a free license for use from the [Product Licensing Site](https://www.xilinx.com/member/forms/license-form.html).
This repository contains an [MLIR-based](https://mlir.llvm.org/) toolchain for AI Engine-enabled devices, such as [AMD Ryzen™ AI](https://www.amd.com/en/products/processors/consumer/ryzen-ai.html) and [Versal™](https://www.xilinx.com/products/technology/ai-engine.html). This repository can be used to generate low-level configurations for the AI Engine portion of these devices. AI Engines are organized as a spatial array of tiles, where each tile contains AI Engine cores and/or memories. The spatial array is connected by stream switches that can be configured to route data between AI Engine tiles scheduled by their programmable Data Movement Accelerators (DMAs). This repository contains MLIR representations, with multiple levels of abstraction, to target AI Engine devices. This enables compilers and developers to program AI Engine cores, as well as describe data movements and array connectivity. A Python API is made available as a convenient interface for generating MLIR design descriptions. Backend code generation is also included, targeting the [aie-rt](https://github.com/Xilinx/aie-rt/tree/main-aie) library. This toolchain uses the AI Engine compiler tool which is part of the AMD Vitis™ software installation: these tools require a free license for use from the [Product Licensing Site](https://www.xilinx.com/member/forms/license-form.html).

This project is primarily intended to support the open-source community, particularly tool builders, with low-level access to AIE devices and enable the development of a wide variety of programming models from higher level abstractions. We provide an example programming flow: Interface Representation for hands-ON (IRON) close-to-metal programming of the AIE-array. IRON is an open access toolkit enabling performance engineers to build fast and efficient, often specialized designs through a set of Python language bindings around the mlir-aie dialect. As such, it contains some examples, however this project is not intended to represent an end-to-end compilation flow for all application designs. If you're looking for an out-of-the-box experience for highly efficient machine learning, check out the [AMD Ryzen™ AI Software Platform](https://github.com/amd/RyzenAI-SW/).

Expand Down
8 changes: 4 additions & 4 deletions programming_guide/section-1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ Then we declare a structural design function that will expand into MLIR code whe
def mlir_aie_design():
<... AI Engine device, blocks, and connections ...>
```
Let's look at how we declare the AI Engine device, blocks, and connections. We start off by declaring our AIE device via `@device(AIEDevice.npu)` or `@device(AIEDevice.xcvc1902)`. The blocks and connections themselves will then be declared inside the `def device_body():`. Here, we instantiate our AI Engine blocks, which are AIE compute tiles in this first example.
Let's look at how we declare the AI Engine device, blocks, and connections. We start off by declaring our AIE device via `@device(AIEDevice.npu1_1col)` or `@device(AIEDevice.xcvc1902)`. The blocks and connections themselves will then be declared inside the `def device_body():`. Here, we instantiate our AI Engine blocks, which are AIE compute tiles in this first example.

The arguments for the tile declaration are the tile coordinates (column, row). We assign each declared tile to a variable in our Python program.

> **NOTE:** The actual tile coordinates used on the device when the program is run may deviate from the ones declared here. For example, on the NPU on Ryzen™ AI (`@device(AIEDevice.npu)`), these coordinates tend to be relative coordinates as the runtime scheduler may assign it to a different available column during runtime.
```
# Device declaration - here using aie2 device NPU
@device(AIEDevice.npu)
@device(AIEDevice.npu1_1col)
def device_body():
# Tile declarations
Expand All @@ -54,7 +54,7 @@ Next to the compute tiles, an AIE-array also contains data movers for accessing

```
# Device declaration - here using aie2 device NPU
@device(AIEDevice.npu)
@device(AIEDevice.npu1_1col)
def device_body():
# Tile declarations
Expand All @@ -78,7 +78,7 @@ Next to the compute tiles, an AIE-array also contains data movers for accessing
Qualify the `print(ctx.module)` call with a check on `ctx.module.operation.verify()` using a code block like the following:
```
res = ctx.module.operation.verify()
if(res == True):
if res == True:
print(ctx.module)
else:
print(res)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ As was explained in the Introduction [section](../../section-2a/README.md#initia

<img src="./../../../assets/Broadcast.png" height="200">

For more low-level details regarding how the objects in the Object FIFO are transferred via the AXI stream through the DMAs of the producer and consumer tiles please see the mlir-aie [tutorials](/mlir-aie/tutorials/tutorial-7/). They are, however, not required to understand or use the Object FIFO API.
For more low-level details regarding how the objects in the Object FIFO are transferred via the AXI stream through the DMAs of the producer and consumer tiles please see the mlir-aie [tutorials](/mlir_tutorials/tutorial-7/). They are, however, not required to understand or use the Object FIFO API.

Below is an example of the Object FIFO `of0` shown in the previous figure. It has a depth of `3` with one producer tile A and three consumer tiles B, C and D:
```python
Expand Down
24 changes: 24 additions & 0 deletions programming_guide/section-2/section-2d/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
##===- Makefile -----------------------------------------------------------===##
#
# This file licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##

srcdir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

include ${srcdir}/../../../programming_examples/makefile-common

all: build/aie.mlir build/aiemulti.mlir

build/aie.mlir: ${srcdir}/aie2.py
mkdir -p ${@D}
python3 $< > $@

build/aiemulti.mlir: ${srcdir}/aie2_multi.py
mkdir -p ${@D}
python3 $< > $@

clean:
rm -rf build
6 changes: 5 additions & 1 deletion programming_guide/section-2/section-2d/aie2.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ def core_body():
yield_([])

# Print the mlir conversion
print(ctx.module)
res = ctx.module.operation.verify()
if res == True:
print(ctx.module)
else:
print(res)


# Call design function to generate mlir code to stdout
Expand Down
6 changes: 5 additions & 1 deletion programming_guide/section-2/section-2d/aie2_multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ def core_body():
yield_([])

# Print the mlir conversion
print(ctx.module)
res = ctx.module.operation.verify()
if res == True:
print(ctx.module)
else:
print(res)


# Call design function to generate mlir code to stdout
Expand Down
7 changes: 7 additions & 0 deletions programming_guide/section-2/section-2d/run_makefile.lit
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// (c) Copyright 2024 Advanced Micro Devices, Inc.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// REQUIRES: ryzen_ai, chess
//
// RUN: make -f %S/Makefile clean
// RUN: make -f %S/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
##===- Makefile -----------------------------------------------------------===##
#
# This file licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
##===----------------------------------------------------------------------===##

srcdir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

include ${srcdir}/../../../../programming_examples/makefile-common

all: build/aie.mlir

build/aie.mlir: ${srcdir}/single_buffer.py
mkdir -p ${@D}
python3 $< > $@

clean:
rm -rf build
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// (c) Copyright 2024 Advanced Micro Devices, Inc.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// REQUIRES: ryzen_ai, chess
//
// RUN: make -f %S/Makefile clean
// RUN: make -f %S/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def single_buffer():
with mlir_mod_ctx() as ctx:

@device(AIEDevice.npu)
@device(AIEDevice.npu1_1col)
def device_body():
memRef_16_ty = T.memref(16, T.i32())

Expand Down Expand Up @@ -52,7 +52,11 @@ def core_body():
of_in.release(ObjectFifoPort.Consume, 1)
yield_([])

print(ctx.module)
res = ctx.module.operation.verify()
if res == True:
print(ctx.module)
else:
print(res)


single_buffer()
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
#
##===----------------------------------------------------------------------===##

include ../../../../programming_examples/makefile-common
srcdir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

include ${srcdir}/../../../../programming_examples/makefile-common

targetname = ext_to_core
devicename = npu
col = 0

all: build/final.xclbin build/insts.txt

build/aie.mlir: ext_to_core.py
build/aie.mlir: ${srcdir}/ext_to_core.py
mkdir -p ${@D}
python3 $< ${devicename} ${col} > $@

Expand All @@ -23,16 +25,16 @@ build/final.xclbin: build/aie.mlir
cd ${@D} && aiecc.py --aie-generate-cdo --no-compile-host --xclbin-name=${@F} \
--aie-generate-npu --npu-insts-name=insts.txt $(<:%=../%)

${targetname}.exe: test.cpp
${targetname}.exe: ${srcdir}/test.cpp
rm -rf _build
mkdir -p _build
cd _build && ${powershell} cmake .. -DTARGET_NAME=${targetname}
cd _build && ${powershell} cmake -E env CXXFLAGS="-std=c++23 -ggdb" cmake ${srcdir} -D CMAKE_C_COMPILER=gcc-13 -D CMAKE_CXX_COMPILER=g++-13 -DTARGET_NAME=${targetname}
cd _build && ${powershell} cmake --build . --config Release
ifeq "${powershell}" "powershell.exe"
cp _build/${targetname}.exe $@
else
cp _build/${targetname} $@
endif
endif

run: ${targetname}.exe build/final.xclbin build/insts.txt
${powershell} ./$< -x build/final.xclbin -i build/insts.txt -k MLIR_AIE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def external_mem_to_core():
with mlir_mod_ctx() as ctx:

@device(AIEDevice.npu)
@device(AIEDevice.npu1_1col)
def device_body():
memRef_24_ty = T.memref(24, T.i32())

Expand Down Expand Up @@ -62,7 +62,11 @@ def sequence(inTensor, notUsed, outTensor):
)
npu_sync(column=0, row=0, direction=0, channel=0)

print(ctx.module)
res = ctx.module.operation.verify()
if res == True:
print(ctx.module)
else:
print(res)


external_mem_to_core()

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// (c) Copyright 2024 Advanced Micro Devices, Inc.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// REQUIRES: ryzen_ai, chess
//
// RUN: make -f %S/Makefile clean
// RUN: make -f %S/Makefile
// RUN: %run_on_npu make -f %S/Makefile run | FileCheck %s
// CHECK: PASS!
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
#
##===----------------------------------------------------------------------===##

include ../../../../programming_examples/makefile-common
srcdir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

include ${srcdir}/../../../../programming_examples/makefile-common

targetname = ext_to_core_L2
devicename = npu
col = 0

all: build/final.xclbin build/insts.txt

build/aie.mlir: ext_to_core_L2.py
build/aie.mlir: ${srcdir}/ext_to_core_L2.py
mkdir -p ${@D}
python3 $< ${devicename} ${col} > $@

Expand All @@ -23,16 +25,16 @@ build/final.xclbin: build/aie.mlir
cd ${@D} && aiecc.py --aie-generate-cdo --no-compile-host --xclbin-name=${@F} \
--aie-generate-npu --npu-insts-name=insts.txt $(<:%=../%)

${targetname}.exe: test.cpp
${targetname}.exe: ${srcdir}/test.cpp
rm -rf _build
mkdir -p _build
cd _build && ${powershell} cmake .. -DTARGET_NAME=${targetname}
cd _build && ${powershell} cmake -E env CXXFLAGS="-std=c++23 -ggdb" cmake ${srcdir} -D CMAKE_C_COMPILER=gcc-13 -D CMAKE_CXX_COMPILER=g++-13 -DTARGET_NAME=${targetname}
cd _build && ${powershell} cmake --build . --config Release
ifeq "${powershell}" "powershell.exe"
cp _build/${targetname}.exe $@
else
cp _build/${targetname} $@
endif
endif

run: ${targetname}.exe build/final.xclbin build/insts.txt
${powershell} ./$< -x build/final.xclbin -i build/insts.txt -k MLIR_AIE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
def external_mem_to_core_L2():
with mlir_mod_ctx() as ctx:

@device(AIEDevice.npu)
@device(AIEDevice.npu1_1col)
def device_body():
memRef_24_ty = T.memref(24, T.i32())
memRef_8_ty = T.memref(8, T.i32())
Expand Down Expand Up @@ -66,7 +66,11 @@ def sequence(inTensor, notUsed, outTensor):
)
npu_sync(column=0, row=0, direction=0, channel=0)

print(ctx.module)
res = ctx.module.operation.verify()
if res == True:
print(ctx.module)
else:
print(res)


external_mem_to_core_L2()

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// (c) Copyright 2024 Advanced Micro Devices, Inc.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// REQUIRES: ryzen_ai, chess
//
// RUN: make -f %S/Makefile clean
// RUN: make -f %S/Makefile
// RUN: %run_on_npu make -f %S/Makefile run | FileCheck %s
// CHECK: PASS!
Loading

0 comments on commit c9046f7

Please sign in to comment.