diff --git a/programming_guide/README.md b/programming_guide/README.md index f029f3237c..9a3ec8bc9d 100644 --- a/programming_guide/README.md +++ b/programming_guide/README.md @@ -10,7 +10,7 @@ # MLIR-AIE Programming Guide -MLIR-AIE is an MLIR-based representation for AI Engine design. It provides a foundation from which complex and performant AI Engine designs can be defined and is supported by simulation and hardware impelemenation infrastructure. To better understand how AI Engine designs are defined at the MLIR level, it is recommended that you spend some time going through the [tutorial course](../tutorials/). However, this programming guide is intended to lead you through a higher level abstraction (python) of the underlying MLIR-AIE framework and provide design examples and programming tips to allow users to build designs directly. Keep in mind also that MLIR-AIE is a foundational layer in a AI Engine software development framework and while this guide provides a programmer's view for using AI Engines, it also serves as a lower layer for higher abstraction MLIR layers such as [MLIR-AIR](https://github.com/Xilinx/mlir-air). +MLIR-AIE is an MLIR-based representation for AI Engine design. It provides a foundation from which complex and performant AI Engine designs can be defined and is supported by simulation and hardware impelemenation infrastructure. To better understand how AI Engine designs are defined at the MLIR level, it is recommended that you spend some time going through the [MLIR tutorial](../tutorials/) material. However, this programming guide is intended to lead you through a higher level abstraction (python) of the underlying MLIR-AIE framework and provide design examples and programming tips to allow users to build designs directly. Keep in mind also that MLIR-AIE is a foundational layer in a AI Engine software development framework and while this guide provides a programmer's view for using AI Engines, it also serves as a lower layer for higher abstraction MLIR layers such as [MLIR-AIR](https://github.com/Xilinx/mlir-air). ## Outline
Section 1 - Basic AI Engine building blocks (tiles and buffers) diff --git a/programming_guide/section-1/README.md b/programming_guide/section-1/README.md index 1205f1e17f..c418ba735c 100644 --- a/programming_guide/section-1/README.md +++ b/programming_guide/section-1/README.md @@ -10,6 +10,36 @@ # Section 1 - Basic AI Engine building blocks (tiles and buffers) +When we program for AI Engines, our MLIR-AIE framework serves as the entry point to declare and configure the structural building blocks of the entire AI Engine array. Details for these building blocks, along with the general architecture of AI Engines are breifly described in the top page of [MLIR tutorials](../tutorials) materials. Read through that synopsis first before continuing here. + +In this programming guide, we will be utilizing the python bindings of MLIR-AIE components to describe our system and the tile level. Later on, when we focus in on kernel programming, we will programming in C/C++. Let's first look at a basic python source file for a MLIR-AIE design. + +``` +from aie.dialects.aie import * # primary mlir-aie dialect definitions +from aie.extras.context import mlir_mod_ctx # mlir ctx wrapper + +# My program definition +def mlir_aie_design(): + # ctx wrapper - needed to convert python to mlir + with mlir_mod_ctx() as ctx: + + # device declaration - here using aie2 device xcvc1902 + @device(AIEDevice.xcvc1902) + def device_body(): + + # Tile declarations + ComputeTile = tile(1, 4) + + # Buffer declarations + ComputeBuffer = buffer(ComputeTile, (8,), T.i32(), name = "a14") + + # print the mlir conversion + print(ctx.module) + +# Call my program +mlir_aie_design() +``` + * Introduce AI Engine building blocks with references to Tutorial material * Give example of python binded MLIR source for defining tiles and buffers diff --git a/programming_guide/section-2/README.md b/programming_guide/section-2/README.md index b398a5e4d7..abb2b69b3d 100644 --- a/programming_guide/section-2/README.md +++ b/programming_guide/section-2/README.md @@ -1,14 +1,35 @@ - -# Section 2- My First Program +# Section 2 - Data Movement (Object FIFOs) -* Introduce example of first simple program (Bias Add) -* Illustrate how built-in simulation of single core design +In this section of the programming guide, we introduce the Object FIFO high-level communication primitive used to describe the data movement within the AIE array. At the end of this guide you will: +1. have a high-level understanding of the communication primitive API, +2. have learned how to initialize and access an Object FIFO through meaningful design examples, +3. understand the design decisions which led to current limitations and/or restrictions in the Object FIFO design, +4. know where to find more in-depth material of the Object FIFO implementation and lower-level lowering. + +To understand the need for a data movement abstraction we must first understand the hardware architecture with which we are working. The AIE array is a spatial compute architecture with explicit data movement requirements. Each compute unit of the array works on data that is stored within its L1 memory module and that data needs to be explicitly moved there as part of the AIE's array global data movement configuration. This configuration involves several specialized hardware resources which handle the data movement over the entire array in such a way that data arrives at its destination without loss. The Object FIFO provides users with a way to specify the data movement in a more human comprehensible and accessible manner without sacrificing some of the more advanced control possibilities which the hardware provides. + +*Note: For more in-depth, low-level material on Object FIFO programming in MLIR please see the MLIR-AIE [tutorials](/mlir-aie/tutorials/).* + +This guide is split into three sections, where each section builds on top of the previous ones: + +
Section 2a - Introduction + +
+
Section 2b - Key Object FIFO Patterns + +
+
Section 2c - Data Layout Transformations + +
+
Section 2d - Programming for multiple cores +
diff --git a/programming_guide/section-3/design_example_1/README.md b/programming_guide/section-2/design_example_1/README.md similarity index 99% rename from programming_guide/section-3/design_example_1/README.md rename to programming_guide/section-2/design_example_1/README.md index 59c697a89c..8cbefaba1a 100644 --- a/programming_guide/section-3/design_example_1/README.md +++ b/programming_guide/section-2/design_example_1/README.md @@ -49,7 +49,7 @@ class object_fifo: ``` such that other actors may acquire it in the future. The acquire and release operations both take an additional port attribute which can be either "Produce" or "Consume". The use of this attribute is ... (TODO). -## Tutorial 3 Lab +## Tutorial 2 Lab 1. Read through the [/objectfifo_ver/aie.mlir](aie.mlir) design. In which tile and its local memory will the objectfifo lowering generate the buffer and its lock? diff --git a/programming_guide/section-3/design_example_1/aie.py b/programming_guide/section-2/design_example_1/aie.py similarity index 100% rename from programming_guide/section-3/design_example_1/aie.py rename to programming_guide/section-2/design_example_1/aie.py diff --git a/programming_guide/section-3/section-3a/README.md b/programming_guide/section-2/section-2a/README.md similarity index 96% rename from programming_guide/section-3/section-3a/README.md rename to programming_guide/section-2/section-2a/README.md index cbc5996959..21e6d2af68 100644 --- a/programming_guide/section-3/section-3a/README.md +++ b/programming_guide/section-2/section-2a/README.md @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===//--> -# Section 3a - Introduction +# Section 2a - Introduction ### Initializing an Object FIFO @@ -28,9 +28,9 @@ class object_fifo: dimensionsFromStreamPerConsumer=None, ) ``` -We will now go over each of the inputs, what they represents and why they are required by the abstraction. We will first focus on the mandatory inputs and in a later section of the guide on the default valued ones (see Data Layout Transformations in [section-3c](../section-3c/README.md#data-layout-transformations)). +We will now go over each of the inputs, what they represents and why they are required by the abstraction. We will first focus on the mandatory inputs and in a later section of the guide on the default valued ones (see Data Layout Transformations in [section-2c](../section-2c/README.md#data-layout-transformations)). -First of all, an Object FIFO has a unique `name`. It functions as an ordered buffer that has `depth`-many objects of specified `datatype`. Currently, all objects in an Object FIFO have to be of the same datatype. The datatype is a tensor-like attribute where the size of the tensor and the type of the individual elements are specified at the same time (i.e. `<16xi32>`). The `depth` can be either an integer or an array of integers. The latter is used to support a specific dependency that can arise when working with multiple Object FIFOs and it is further explained in the Key Object FIFO Patterns [section](../section-3b/README.md#broadcast). +First of all, an Object FIFO has a unique `name`. It functions as an ordered buffer that has `depth`-many objects of specified `datatype`. Currently, all objects in an Object FIFO have to be of the same datatype. The datatype is a tensor-like attribute where the size of the tensor and the type of the individual elements are specified at the same time (i.e. `<16xi32>`). The `depth` can be either an integer or an array of integers. The latter is used to support a specific dependency that can arise when working with multiple Object FIFOs and it is further explained in the Key Object FIFO Patterns [section](../section-2b/README.md#broadcast). An Object FIFO is created between a producer or source tile and a consumer or destination tile. Below, you can see an example of an Object FIFO created between producer tile A and consumer tile B: ``` @@ -40,7 +40,7 @@ of0 = object_fifo("objfifo0", A, B, 3, T.memref(256, T.i32())) ``` The created Object FIFO is stored in the `0f0` variable and is named `objfifo0`. It has a depth of `3` objects of datatype `<256xi32>`. -As you will see in the Key Object FIFO Patterns [section](../section-3b/README.md#key-object-fifo-patterns), an Object FIFO can have multiple consumer tiles, which describes a broadcast connection from the source tile to all of the consumer tiles. As such, the `consumerTiles` input can be either a single tile or an array of tiles. This is not the case for the `producerTile` input as currently the Object FIFO does not support multiple producers. +As you will see in the Key Object FIFO Patterns [section](../section-2b/README.md#key-object-fifo-patterns), an Object FIFO can have multiple consumer tiles, which describes a broadcast connection from the source tile to all of the consumer tiles. As such, the `consumerTiles` input can be either a single tile or an array of tiles. This is not the case for the `producerTile` input as currently the Object FIFO does not support multiple producers. ### Accessing the objects of an Object FIFO diff --git a/programming_guide/section-3/section-3b/README.md b/programming_guide/section-2/section-2b/README.md similarity index 98% rename from programming_guide/section-3/section-3b/README.md rename to programming_guide/section-2/section-2b/README.md index 642c924fdf..05f1d1ca16 100644 --- a/programming_guide/section-3/section-3b/README.md +++ b/programming_guide/section-2/section-2b/README.md @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===//--> -# Section 3b - Key Object FIFO Patterns +# Section 2b - Key Object FIFO Patterns The Object FIFO primitive supports several data movement patterns through its inputs and its member functions. We will now describe each of the currently supported patterns and provide links to more in-depth practical code examples that showcase each of them. @@ -18,7 +18,7 @@ The Object FIFO primitive supports several data movement patterns through its in ### Broadcast -As was explained in the Introduction [section](../section-3a/README.md#initializing-an-object-fifo) section, the `consumerTiles` input can be either a single tile or an array of tiles. When the input is specified as an array of tiles, this creates a broadcast communication from a single producer tile to multiple consumer tiles. The data from the producer tile's memory module is sent to each of the consumer tiles' memory modules via the AXI stream interconnect, which handles the back-pressure from consumers with different execution times. The AXI stream is also where the data is copied at a low-level before being sent to each of the consumers. +As was explained in the Introduction [section](../section-2a/README.md#initializing-an-object-fifo) section, the `consumerTiles` input can be either a single tile or an array of tiles. When the input is specified as an array of tiles, this creates a broadcast communication from a single producer tile to multiple consumer tiles. The data from the producer tile's memory module is sent to each of the consumer tiles' memory modules via the AXI stream interconnect, which handles the back-pressure from consumers with different execution times. The AXI stream is also where the data is copied at a low-level before being sent to each of the consumers. 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 [tutorials](/mlir-aie/tutorials/tutorial-7/). diff --git a/programming_guide/section-3/section-3c/README.md b/programming_guide/section-2/section-2c/README.md similarity index 89% rename from programming_guide/section-3/section-3c/README.md rename to programming_guide/section-2/section-2c/README.md index 7a1d9568bd..7ad36579bc 100644 --- a/programming_guide/section-3/section-3c/README.md +++ b/programming_guide/section-2/section-2c/README.md @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===//--> -# Section 3c - Data Layout Transformations +# Section 2c - Data Layout Transformations * dimensionsToStream, dimensionsFromStreamPerConsumer diff --git a/programming_guide/section-3/section-3d/README.md b/programming_guide/section-2/section-2d/README.md similarity index 91% rename from programming_guide/section-3/section-3d/README.md rename to programming_guide/section-2/section-2d/README.md index 5fb14329de..c34928417f 100644 --- a/programming_guide/section-3/section-3d/README.md +++ b/programming_guide/section-2/section-2d/README.md @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===//--> -# Section 3d - Programming for multiple cores +# Section 2d - Programming for multiple cores * explain how to go from code written for a single core to code written like in the visual pipelines, with for loops over multiple cores accessing several objfifos diff --git a/programming_guide/section-3/README.md b/programming_guide/section-3/README.md index a664d7dfde..49e78a6908 100644 --- a/programming_guide/section-3/README.md +++ b/programming_guide/section-3/README.md @@ -1,35 +1,14 @@ - -# Section 3 - Data Movement (Object FIFOs) +# Section 3 - My First Program -In this section of the programming guide, we introduce the Object FIFO high-level communication primitive used to describe the data movement within the AIE array. At the end of this guide you will: -1. have a high-level understanding of the communication primitive API, -2. have learned how to initialize and access an Object FIFO through meaningful design examples, -3. understand the design decisions which led to current limitations and/or restrictions in the Object FIFO design, -4. know where to find more in-depth material of the Object FIFO implementation and lower-level lowering. - -To understand the need for a data movement abstraction we must first understand the hardware architecture with which we are working. The AIE array is a spatial compute architecture with explicit data movement requirements. Each compute unit of the array works on data that is stored within its L1 memory module and that data needs to be explicitly moved there as part of the AIE's array global data movement configuration. This configuration involves several specialized hardware resources which handle the data movement over the entire array in such a way that data arrives at its destination without loss. The Object FIFO provides users with a way to specify the data movement in a more human comprehensible and accessible manner without sacrificing some of the more advanced control possibilities which the hardware provides. - -*Note: For more in-depth, low-level material on Object FIFO programming in MLIR please see the MLIR-AIE [tutorials](/mlir-aie/tutorials/).* - -This guide is split into three sections, where each section builds on top of the previous ones: - -
Section 3a - Introduction - -
-
Section 3b - Key Object FIFO Patterns - -
-
Section 3c - Data Layout Transformations - -
-
Section 3d - Programming for multiple cores -
+* Introduce example of first simple program (Bias Add) +* Illustrate how built-in simulation of single core design