Skip to content

Commit

Permalink
New objectFifo syntax using symbols (#581)
Browse files Browse the repository at this point in the history
* started modifying registerExternalBuffersOp

* Replace objectFifo value with symbol attr in other ops.

* Fixed error where split objectFifos weren't replaced. Started replacing symbols in LinkOp.

* Changed all objFifo ops to use symbols instead of SSA values.

* Restored some tests. Will rewrite all tests in separate commits.

* Modify AIE.td doc.

* Finished updating AIE.td.

* Typo.

* Remove objectFifo SSA return type. Replace with objectFifo type.

* Modified all instances of the createObjectFifo operation.

* Started modifying acquire/release operations.

* Modified all instances of objectFifo acquire and release operations.

* Modified all instances of objectFifo registerExternalBuffers operation.

* Modified all instances of the objectFifo registerProcess operation.

* Modified all unit tests.

* Updated objectFifo documentation.

* Modified all instances of objectFifo link and shimDMAAllocation operations.

* Clang format

* Handle warnings

* Clang format

* Fix failing tests

* Fix test

* Add missing commas

* Change syntax of LinkOp from 'to' to '->'.

---------

Co-authored-by: abisca <andrab@amd.com>
  • Loading branch information
AndraBisca and abisca authored Aug 16, 2023
1 parent 59f6ba2 commit de5ff6a
Show file tree
Hide file tree
Showing 70 changed files with 1,756 additions and 1,637 deletions.
55 changes: 42 additions & 13 deletions docs/AIEDesignPatterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,15 @@ XAieTile_LockRelease(&(TileInst[7][2]), 1, 0x1, 0);
[ObjectFIFO Example](https://github.com/Xilinx/mlir-aie/tree/main/test/objectFifo-stateful-transform/non_adjacency_test_1.aie.mlir)

An objectFIFO can be established between two or more tiles. Broadcast is possible from one producer tile to multiple consumer tiles.
Unlike a typical FIFO, elements are not pushed to nor popped from the objectFIFO. Instead, a pool of memory elements is allocated to the objectFIFO.
Unlike a typical FIFO, elements are not pushed to nor popped from the objectFIFO. Instead, a pool of memory elements is allocated to the objectFIFO by the objectFIFO lowering pass, i.e., AIEObjectFifoStatefulTransform.mlir.

Processes can then write to and read from these memory elements after acquiring them.

Define two tiles and create an AIE.objectFifo of depth two between them, with the two elements being of type <memref<16xi32>>:
Define two tiles and create an AIE.objectFifo named @of0 of depth two between them, with the two elements being of type <memref<16xi32>>:
```
%tile12 = AIE.tile(1, 2)
%tile33 = AIE.tile(3, 3)
%objFifo = AIE.objectFifo.createObjectFifo(%tile12, {tile33}, 2) : !AIE.objectFifo<memref<16xi32>>
AIE.objectFifo @of0 (%tile12, {tile33}, 2 : i32) : !AIE.objectFifo<memref<16xi32>>
```
After subsequent conversion passes, each of the objectFifo elements is instantiated as an AIE.buffer with an AIE.lock.

Expand All @@ -367,10 +368,10 @@ Operations can be performed on the objectFIFO in the cores: elements can be acqu
%height = arith.constant 12 : index
scf.for %indexInHeight = %c0 to %height step %c1 {
%subview = AIE.objectFifo.acquire<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%subview = AIE.objectFifo.acquire @of0 (Produce, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%elem0 = AIE.objectFifo.subview.access %subview[0] : !AIE.objectFifoSubview<memref<16xi32>> -> memref<16xi32>
call @some_work(%elem0) : (memref<16xi32>) -> ()
AIE.objectFifo.release<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1)
AIE.objectFifo.release @of0 (Produce, 1)
}
AIE.end
Expand All @@ -382,10 +383,10 @@ Operations can be performed on the objectFIFO in the cores: elements can be acqu
%height = arith.constant 12 : index
scf.for %indexInHeight = %c0 to %height step %c1 {
%subview = AIE.objectFifo.acquire<Consume>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%subview = AIE.objectFifo.acquire @of0 (Consume, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%elem0 = AIE.objectFifo.subview.access %subview[0] : !AIE.objectFifoSubview<memref<16xi32>> -> memref<16xi32>
call @some_work(%elem0) : (memref<16xi32>) -> ()
AIE.objectFifo.release<Consume>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1)
AIE.objectFifo.release @of0 (Consume, 1)
}
AIE.end
Expand All @@ -400,28 +401,56 @@ For correct execution, loops that contain objectFIFO operations must be unrolled
%height = arith.constant 12 : index
scf.for %indexInHeight = %c0 to %height step %c2 {
%subview0 = AIE.objectFifo.acquire<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%subview0 = AIE.objectFifo.acquire @of0 (Produce, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%elem00 = AIE.objectFifo.subview.access %subview0[0] : !AIE.objectFifoSubview<memref<16xi32>> -> memref<16xi32>
call @some_work(%elem00) : (memref<16xi32>) -> ()
AIE.objectFifo.release<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1)
AIE.objectFifo.release @of0 (Produce, 1)
%subview1 = AIE.objectFifo.acquire<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%subview1 = AIE.objectFifo.acquire @of0 (Produce, 1) : !AIE.objectFifoSubview<memref<16xi32>>
%elem10 = AIE.objectFifo.subview.access %subview1[0] : !AIE.objectFifoSubview<memref<16xi32>> -> memref<16xi32>
call @some_work(%elem10) : (memref<16xi32>) -> ()
AIE.objectFifo.release<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, 1)
AIE.objectFifo.release @of0 (Produce, 1)
}
AIE.end
}
```

ObjectFIFOs can be established between tiles on the shim row and AIE tiles in order to bring data in from or out to external memory locations. These external memory locations are pointed to using AIE.external_buffer operations and they need to be explicitly registered to an objectFIFO so that it knows where the data has been allocated externally (in this case, the objectFIFO lowering will only allocate memory elements required by AIE tiles):
```
module @objectFIFO {
%tile10 = AIE.tile(1, 0)
%tile33 = AIE.tile(3, 3)
AIE.objectFifo @of1 (%tile10, {tile33}, 2 : i32) : !AIE.objectFifo<memref<16xi32>>
%ext_buffer_in_0 = AIE.external_buffer {sym_name = "ext_buffer_in_0"}: memref<64xi32>
%ext_buffer_in_1 = AIE.external_buffer {sym_name = "ext_buffer_in_1"}: memref<64xi32>
AIE.objectFifo.registerExternalBuffers @of1 (%tile10, {%ext_buffer_in_0, %ext_buffer_in_1}) : (memref<64xi32>, memref<64xi32>)
}
```

It is possible to copy data from one objectFifo to another. This copy can be done explicitly within the AIE cores, or implicitly using the tile DMAs. The latter case is not as much a copy as it is re-using the same memory buffers when receiving data on an input channel and sending the data out on an output channel. At the objectFIFO abstraction, this is called 'linking' two objectFIFOs. It is most commonly done inside of Mem tiles which have more memory than AIE tiles.
```
module @objectFIFO {
%tile20 = AIE.tile(2, 0)
%tile22 = AIE.tile(2, 2)
%tile24 = AIE.tile(2, 4)
AIE.objectFifo @of1 (%tile20, {%tile22}, 2 : i32) : !AIE.objectFifo<memref<16xi32>>
AIE.objectFifo @of2 (%tile22, {%tile24}, 2 : i32) : !AIE.objectFifo<memref<16xi32>>
AIE.objectFifo.link [@of1] -> [@of2] ()
}
```

At a higher abstraction level, a process can be registered to an objectFIFO using access patterns and work functions:
```
module @objectFIFO {
%tile12 = AIE.tile(1, 2)
%tile33 = AIE.tile(3, 3)
%objFifo = AIE.objectFifo.createObjectFifo(%tile12, {tile33}, 2) : !AIE.objectFifo<memref<16xi32>>
AIE.objectFifo @of1 (%tile12, {tile33}, 2 : i32) : !AIE.objectFifo<memref<16xi32>>
%prodAcqPattern = arith.constant dense<[1]> : tensor<1xi32>
%prodRelPattern = arith.constant dense<[1]> : tensor<1xi32>
Expand All @@ -430,7 +459,7 @@ module @objectFIFO {
return
}
AIE.objectFifo.registerProcess<Produce>(%objFifo : !AIE.objectFifo<memref<16xi32>>, %prodAcqPattern : tensor<1xi32>, %prodRelPattern : tensor<1xi32>, @producer_work, %prodLength)
AIE.objectFifo.registerProcess @of1 (Produce, %prodAcqPattern : tensor<1xi32>, %prodRelPattern : tensor<1xi32>, @producer_work, %prodLength)
}
```

Expand Down
Loading

0 comments on commit de5ff6a

Please sign in to comment.