Skip to content

Commit 19b473b

Browse files
authored
Enable reconfiguration through lowerings for aiex.configure and aiex.run (#2775)
1 parent 5b52c47 commit 19b473b

File tree

39 files changed

+2299
-126
lines changed

39 files changed

+2299
-126
lines changed

include/aie/Conversion/AIEToConfiguration/AIEToConfiguration.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ namespace xilinx::AIE {
1919

2020
class DeviceOp;
2121

22+
// --------------------------------------------------------------------------
23+
// Device configuration
24+
// --------------------------------------------------------------------------
25+
26+
// an enum to represent the output type of the transaction binary
27+
enum AIEToConfigurationOutputType {
28+
Transaction,
29+
ControlPacket,
30+
};
31+
2232
std::unique_ptr<mlir::OperationPass<xilinx::AIE::DeviceOp>>
2333
createConvertAIEToTransactionPass();
2434

@@ -29,6 +39,58 @@ std::optional<mlir::ModuleOp>
2939
convertTransactionBinaryToMLIR(mlir::MLIRContext *ctx,
3040
std::vector<uint8_t> &binary);
3141

42+
// Generate transaction binary and insert configuration operations at the
43+
// current insertion point
44+
mlir::LogicalResult
45+
generateAndInsertConfigOps(mlir::OpBuilder &builder,
46+
xilinx::AIE::DeviceOp device,
47+
llvm::StringRef clElfDir = "",
48+
AIEToConfigurationOutputType outputType =
49+
AIEToConfigurationOutputType::Transaction);
50+
51+
// --------------------------------------------------------------------------
52+
// Device reset
53+
// --------------------------------------------------------------------------
54+
55+
// Enum for specifying which tile types to reset
56+
enum class ResetTileType : unsigned {
57+
None = 0,
58+
ShimNOC = 1 << 0,
59+
MemTile = 1 << 1,
60+
CoreTile = 1 << 2,
61+
All = ShimNOC | MemTile | CoreTile
62+
};
63+
64+
inline bool hasFlag(ResetTileType value, ResetTileType flag) {
65+
return (static_cast<unsigned>(value) & static_cast<unsigned>(flag)) != 0;
66+
}
67+
68+
// Enum for specifying when to reset
69+
enum class ResetMode {
70+
Never, // Never perform reset
71+
IfUsed, // Reset only if the tile is used in the device
72+
IfUsedFineGrained, // Reset only individual locks/connections that are used
73+
IfChanged, // Reset only if the tile configuration changed from previous
74+
IfChangedFineGrained, // Reset only individual locks/connections that changed
75+
Always // Reset all tiles of the specified type
76+
};
77+
78+
// Configuration for different reset operations
79+
struct ResetConfig {
80+
ResetTileType tileType;
81+
ResetMode mode;
82+
83+
ResetConfig(ResetTileType tt = ResetTileType::None,
84+
ResetMode m = ResetMode::Never)
85+
: tileType(tt), mode(m) {}
86+
};
87+
88+
// Insert reset operations at the current insertion point
89+
mlir::LogicalResult generateAndInsertResetOps(
90+
mlir::OpBuilder &builder, xilinx::AIE::DeviceOp device,
91+
ResetConfig dmaConfig, ResetConfig switchConfig, ResetConfig lockConfig,
92+
ResetConfig coreConfig, xilinx::AIE::DeviceOp previousDevice);
93+
3294
} // namespace xilinx::AIE
3395

3496
#endif // AIE_CONVERSION_AIETOCONFIGURATION_AIETOCONFIGURATION_H

include/aie/Dialect/AIE/IR/AIEOps.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,7 @@ def AIE_RuntimeSequenceOp : AIE_Op<"runtime_sequence", [
21602160
static llvm::StringRef getDefaultRuntimeSequenceName() { return "sequence"; }
21612161
static RuntimeSequenceOp getForSymbolInDevice(DeviceOp module, llvm::StringRef symbol);
21622162
static RuntimeSequenceOp getForSymbolInDeviceOrError(DeviceOp module, llvm::StringRef symbol);
2163+
llvm::LogicalResult verifyBeforeMaterialization();
21632164
}];
21642165
let extraClassDefinition = [{
21652166
}];

include/aie/Dialect/AIEX/AIEUtils.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include "aie/Dialect/AIE/IR/AIEDialect.h"
1212
#include "mlir/Dialect/MemRef/IR/MemRef.h"
13+
#include "mlir/IR/Value.h"
1314

1415
using namespace mlir;
1516

@@ -20,5 +21,20 @@ memref::GlobalOp getOrCreateDataMemref(OpBuilder &builder, AIE::DeviceOp dev,
2021
mlir::Location loc,
2122
ArrayRef<uint32_t> words);
2223

24+
// Result of tracing through subview/cast operations to a block argument for
25+
// traceSubviewToBlockArgument function.
26+
struct SubviewTraceResult {
27+
BlockArgument rootArg;
28+
int64_t offsetInBytes;
29+
};
30+
31+
// Trace through memref.subview, memref.cast, and memref.reinterpret_cast
32+
// operations until the referenced SSA value is a block argument.
33+
//
34+
// Returns the root block argument and cumulative byte offset, or std::nullopt
35+
// if the chain doesn't lead to a block argument or contains unsupported ops.
36+
//
37+
// This function checks that all subviews remain static and contiguous.
38+
std::optional<SubviewTraceResult> traceSubviewToBlockArgument(Value value);
2339
}
2440
} // namespace xilinx

include/aie/Dialect/AIEX/IR/AIEX.td

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,7 @@ def AIE_SelectOp: AIEX_Op<"select", []>, Results<(outs Index)> {
534534
def AIE_ConfigureOp: AIEX_Op<"configure", [
535535
HasParent<"AIE::RuntimeSequenceOp">,
536536
NoTerminator
537-
]>,
538-
Results<(outs Index:$result)>
537+
]>
539538
{
540539
let summary = "Set up a configuration (program memories, stream switches, etc.) on the NPU device.";
541540
let arguments = (

include/aie/Dialect/AIEX/Transforms/AIEXPasses.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>> createAIEDmaToNpuPass();
3232
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>> createAIEXToStandardPass();
3333
std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
3434
createAIEMaterializeBDChainsPass();
35+
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
36+
createAIEMaterializeRuntimeSequencesPass();
3537
std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
3638
createAIEAssignRuntimeSequenceBDIDsPass();
3739
std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
@@ -50,6 +52,8 @@ std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
5052
createAIETxnToControlPacketPass();
5153
std::unique_ptr<mlir::OperationPass<AIE::DeviceOp>>
5254
createAIELegalizeControlPacketPass();
55+
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
56+
createAIEExpandLoadPdiPass();
5357

5458
/// Generate the code for registering passes.
5559
#define GEN_PASS_REGISTRATION

include/aie/Dialect/AIEX/Transforms/AIEXPasses.td

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ def AIEMaterializeBDChains : Pass<"aie-materialize-bd-chains", "AIE::DeviceOp">
160160
];
161161
}
162162

163+
def AIEMaterializeRuntimeSequences : Pass<"aie-materialize-runtime-sequences", "mlir::ModuleOp"> {
164+
let summary = "Turn `aiex.configure` into configuration primitives and inline `aiex.run` calls";
165+
let description = [{
166+
Turns top-level `aiex.configure` into load PDI firmware instructions that set up the requested configuration.
167+
168+
Inlines calls to other runtime sequences using `aiex.run` into the calling runtime sequence, resolving references within them to the device containing the definition.
169+
170+
This pass requires ObjectFIFOs to be lowered first; apply the ObjectFIFO stateful transform before applying this pass.
171+
}];
172+
173+
let constructor = "xilinx::AIEX::createAIEMaterializeRuntimeSequencesPass()";
174+
let dependentDialects = [
175+
"xilinx::AIE::AIEDialect",
176+
"xilinx::AIEX::AIEXDialect",
177+
];
178+
}
179+
163180
def AIEAssignRuntimeSequenceBDIDs : Pass<"aie-assign-runtime-sequence-bd-ids", "AIE::DeviceOp"> {
164181
let summary = "Assign IDs to Buffer Descriptors Configured in the Runtime Sequence";
165182

@@ -254,4 +271,24 @@ def AIELegalizeControlPacket : Pass<"aie-legalize-ctrl-packet", "AIE::DeviceOp">
254271
"xilinx::AIEX::AIEXDialect",
255272
];
256273
}
274+
275+
def AIEExpandLoadPdi : Pass<"aie-expand-load-pdi", "mlir::ModuleOp"> {
276+
let summary = "Expand load_pdi operations to explicit configuration sequences";
277+
let description = [{
278+
This pass transforms `load_pdi { device_ref = @device }` operations as follows:
279+
1. Create an empty device `@empty_N`.
280+
2. Replace the load_pdi with `load_pdi { device_ref = @empty_N }` -- this causes a device reset.
281+
3. Configure the device for the selected design by inserting write32s and blockwrites.
282+
283+
The configuration operations are generated by converting the referenced device's configuration to a transaction binary and then disassembling it into MLIR operations.
284+
}];
285+
286+
let constructor = "xilinx::AIEX::createAIEExpandLoadPdiPass()";
287+
let dependentDialects = [
288+
"mlir::memref::MemRefDialect",
289+
"xilinx::AIE::AIEDialect",
290+
"xilinx::AIEX::AIEXDialect",
291+
];
292+
}
293+
257294
#endif

include/aie/Targets/AIERT.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ struct AIERTControl {
4646
void startTransaction();
4747
void dmaUpdateBdAddr(int col, int row, size_t addr, size_t bdId);
4848
std::vector<uint8_t> exportSerializedTransaction();
49+
mlir::LogicalResult resetPartition();
50+
mlir::LogicalResult resetDMA(int col, int row, bool on);
51+
mlir::LogicalResult resetCore(int col, int row);
52+
mlir::LogicalResult resetCoreUnreset(int col, int row);
53+
mlir::LogicalResult resetSwitch(int col, int row);
54+
mlir::LogicalResult resetLock(int col, int row, int lockId);
55+
mlir::LogicalResult resetSwitchConnection(int col, int row,
56+
WireBundle sourceBundle,
57+
int sourceChannel,
58+
WireBundle destBundle,
59+
int destChannel);
60+
mlir::LogicalResult resetPerfCounters(int col, int row);
4961

5062
private:
5163
const AIETargetModel &targetModel;

0 commit comments

Comments
 (0)