Skip to content

Commit 0d358eb

Browse files
committed
Enable support for drop-in replacement of load_pdi with control packets
1 parent 70882f0 commit 0d358eb

24 files changed

Lines changed: 697 additions & 150 deletions

File tree

include/aie/Conversion/AIEToConfiguration/AIEToConfiguration.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ mlir::LogicalResult generateAndInsertConfigOps(
4343
llvm::StringRef clElfDir = "",
4444
AIEToConfigurationOutputType outputType =
4545
AIEToConfigurationOutputType::Transaction,
46-
std::string blockwrite_prefix = "config_blockwrite_data_");
46+
std::string blockwrite_prefix = "config_blockwrite_data_",
47+
bool skipCtrlPktOverlay = false);
4748

4849
// --------------------------------------------------------------------------
4950
// Device reset

include/aie/Dialect/AIE/Transforms/AIEPasses.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ std::unique_ptr<mlir::OperationPass<DeviceOp>>
5959
createAIEAssignBufferDescriptorIDsPass();
6060
std::unique_ptr<mlir::OperationPass<DeviceOp>>
6161
createAIEObjectFifoLivenessPass();
62-
std::unique_ptr<mlir::OperationPass<DeviceOp>>
62+
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
6363
createAIEGenerateColumnControlOverlayPass();
64-
std::unique_ptr<mlir::OperationPass<DeviceOp>>
64+
std::unique_ptr<mlir::OperationPass<mlir::ModuleOp>>
6565
createAIEGenerateColumnControlOverlayPass(
6666
const AIEGenerateColumnControlOverlayOptions &options);
6767
std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIEAssignTileCtrlIDsPass();

include/aie/Dialect/AIE/Transforms/AIEPasses.td

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ def AIEAssignTileCtrlIDs : Pass<"aie-assign-tile-controller-ids", "DeviceOp"> {
408408
];
409409
}
410410

411-
def AIEGenerateColumnControlOverlay : Pass<"aie-generate-column-control-overlay", "DeviceOp"> {
411+
def AIEGenerateColumnControlOverlay : Pass<"aie-generate-column-control-overlay", "mlir::ModuleOp"> {
412412
let summary = "Spawns streaming interconnect network for column control";
413413
let description = [{
414414
For each column of AIE tiles being employed in the design, spawn a network of control packet
@@ -424,6 +424,10 @@ def AIEGenerateColumnControlOverlay : Pass<"aie-generate-column-control-overlay"
424424
"Flag to generate TCT routing between tile CTRL and shim SOUTH ports. Available options: ['shim-only', 'all-tiles', 'disable'].">,
425425
Option<"clRouteShimDmaToTileCTRL", "route-shim-to-tile-ctrl", "bool", /*default=*/"false",
426426
"Flag to generate routing between shim dma DMA and tile CTRL ports, for configuration.">,
427+
Option<"clStandaloneDeviceOnly", "standalone-device-only", "bool", /*default=*/"false",
428+
"Only emit the standalone @ctrl_pkt_overlay device; do not apply the overlay in place to source devices.">,
429+
Option<"clEmitStandaloneOverlay", "emit-standalone-overlay", "bool", /*default=*/"false",
430+
"Emit a standalone @ctrl_pkt_overlay device (and tag source devices) for the load-pdi-to-ctrl-pkt reconfigure flow. When false, the pass applies the overlay in place only (legacy behavior).">,
427431
];
428432
}
429433

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ def AIE_ConfigureOp: AIEX_Op<"configure", [
346346
{
347347
let summary = "Set up a configuration (program memories, stream switches, etc.) on the NPU device.";
348348
let arguments = (
349-
ins FlatSymbolRefAttr:$symbol
349+
ins FlatSymbolRefAttr:$symbol,
350+
OptionalAttr<AIEX_ExpandMode>:$expand_mode
350351
);
351352

352353
let assemblyFormat = [{
@@ -977,7 +978,8 @@ def AIE_NpuLoadPdiOp: AIEX_Op<"npu.load_pdi", []> {
977978
ins OptionalAttr<FlatSymbolRefAttr>:$device_ref,
978979
DefaultValuedOptionalAttr<I32Attr, "0">:$id,
979980
DefaultValuedOptionalAttr<I32Attr, "0">:$size,
980-
DefaultValuedOptionalAttr<UI64Attr, "0">:$address
981+
DefaultValuedOptionalAttr<UI64Attr, "0">:$address,
982+
OptionalAttr<AIEX_ExpandMode>:$expand_mode
981983
);
982984
let results = (outs );
983985
let assemblyFormat = [{ attr-dict }];

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,15 @@ def ScratchpadParameterKind : I32EnumAttr<"ScratchpadParameterKind",
3333
let cppNamespace = "::xilinx::AIEX";
3434
}
3535

36+
// How a `load_pdi` op should be expanded by the `aie-expand-load-pdi` pass.
37+
def AIEX_ExpandNone : I32EnumAttrCase<"none", 0>;
38+
def AIEX_ExpandWrite32 : I32EnumAttrCase<"write32", 1>;
39+
def AIEX_ExpandCtrlPkt : I32EnumAttrCase<"ctrlpkt", 2>;
40+
41+
def AIEX_ExpandMode : I32EnumAttr<"ExpandMode",
42+
"How to expand a load_pdi op",
43+
[AIEX_ExpandNone, AIEX_ExpandWrite32, AIEX_ExpandCtrlPkt]> {
44+
let cppNamespace = "::xilinx::AIEX";
45+
}
46+
3647
#endif // AIEX_ATTRS

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

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -397,12 +397,27 @@ def AIELegalizeControlPacket : Pass<"aie-legalize-ctrl-packet", "AIE::DeviceOp">
397397
def AIEExpandLoadPdi : Pass<"aie-expand-load-pdi", "mlir::ModuleOp"> {
398398
let summary = "Expand load_pdi operations to explicit configuration sequences";
399399
let description = [{
400-
This pass transforms `load_pdi { device_ref = @device }` operations as follows:
401-
1. Create an empty device `@empty_N`.
402-
2. Replace the load_pdi with `load_pdi { device_ref = @empty_N }` -- this causes a device reset.
403-
3. Configure the device for the selected design by inserting write32s and blockwrites.
404-
405-
The configuration operations are generated by converting the referenced device's configuration to a transaction binary and then disassembling it into MLIR operations.
400+
This pass transforms `load_pdi { device_ref = @device }` operations.
401+
402+
By default (`ctrl-pkt = false`), each op is replaced with:
403+
1. A `load_pdi { device_ref = @empty_N }` op (loading an empty device,
404+
which causes a device reset).
405+
2. A sequence of `aiex.npu.write32`/`aiex.npu.blockwrite` ops that
406+
configure the device.
407+
408+
With `ctrl-pkt = true`, each op is replaced with:
409+
1. A `load_pdi { device_ref = @ctrl_pkt_overlay }` op, which loads the
410+
column control packet overlay needed to stream further configuration
411+
as control packets.
412+
2. A sequence of `aiex.npu.control_packet` ops that configure the device.
413+
414+
The configuration operations are generated by converting the referenced
415+
device's configuration to a transaction binary and then disassembling it
416+
into MLIR operations.
417+
418+
This pass is intended to run after runtime sequence materialization
419+
(i.e., after `aiex.configure` ops have been turned into
420+
`aiex.npu.load_pdi`).
406421
}];
407422

408423
let constructor = "xilinx::AIEX::createAIEExpandLoadPdiPass()";
@@ -411,6 +426,12 @@ def AIEExpandLoadPdi : Pass<"aie-expand-load-pdi", "mlir::ModuleOp"> {
411426
"xilinx::AIE::AIEDialect",
412427
"xilinx::AIEX::AIEXDialect",
413428
];
429+
let options = [
430+
Option<"clCtrlPkt", "ctrl-pkt", "bool", /*default=*/"false",
431+
"If true, lower each load_pdi to an @ctrl_pkt_overlay load_pdi "
432+
"followed by aiex.npu.control_packet ops instead of write32/"
433+
"blockwrite ops with an empty-device reset.">,
434+
];
414435
}
415436

416437
def AIEXInlineTraceConfig : Pass<"aie-inline-trace-config", "AIE::DeviceOp"> {

include/aie/Targets/AIERT.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ struct AIERTControl {
5555
mlir::LogicalResult configureLocksAndBd(mlir::Block &block, int col, int row);
5656
mlir::LogicalResult initLocks(DeviceOp &targetOp);
5757
mlir::LogicalResult initBuffers(DeviceOp &targetOp);
58-
mlir::LogicalResult configureSwitches(DeviceOp &targetOp);
59-
mlir::LogicalResult addInitConfig(DeviceOp &targetOp);
58+
mlir::LogicalResult configureSwitches(DeviceOp &targetOp,
59+
bool skipCtrlPktOverlay = false);
60+
mlir::LogicalResult addInitConfig(DeviceOp &targetOp,
61+
bool skipCtrlPktOverlay = false);
6062
mlir::LogicalResult addCoreEnable(DeviceOp &targetOp);
6163
mlir::LogicalResult addAieElf(uint8_t col, uint8_t row,
6264
const mlir::StringRef elfPath, bool aieSim);

lib/Conversion/AIEToConfiguration/AIEToConfiguration.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,12 @@ static LogicalResult generateTransactions(AIERTControl &ctl,
436436
const StringRef workDirPath,
437437
DeviceOp &targetOp, bool aieSim,
438438
bool enableElfs, bool enableInit,
439-
bool enableCores) {
439+
bool enableCores,
440+
bool skipCtrlPktOverlay = false) {
440441
if (enableElfs && !targetOp.getOps<CoreOp>().empty() &&
441442
failed(ctl.addAieElfs(targetOp, workDirPath, aieSim)))
442443
return failure();
443-
if (enableInit && failed(ctl.addInitConfig(targetOp)))
444+
if (enableInit && failed(ctl.addInitConfig(targetOp, skipCtrlPktOverlay)))
444445
return failure();
445446
if (enableCores && !targetOp.getOps<CoreOp>().empty() &&
446447
failed(ctl.addCoreEnable(targetOp)))
@@ -508,8 +509,9 @@ emitTransactionOps(OpBuilder &builder, Location fallbackLoc,
508509
IntegerAttr addressAttr =
509510
IntegerAttr::get(ui64Ty, llvm::APInt(64, payloadInfo.address));
510511

511-
AIEX::NpuLoadPdiOp::create(builder, loc, nullptr, idAttr, sizeAttr,
512-
addressAttr);
512+
AIEX::NpuLoadPdiOp::create(builder, loc, /*device_ref=*/nullptr, idAttr,
513+
sizeAttr, addressAttr,
514+
/*expand_mode=*/nullptr);
513515
} else if (op.cmd.Opcode == XAie_TxnOpcode::XAIE_IO_CUSTOM_OP_DDR_PATCH) {
514516
if (!op.addressPatch) {
515517
llvm::errs()
@@ -770,7 +772,7 @@ xilinx::AIE::convertTransactionBinaryToMLIR(mlir::MLIRContext *ctx,
770772
LogicalResult xilinx::AIE::generateAndInsertConfigOps(
771773
OpBuilder &builder, xilinx::AIE::DeviceOp device, llvm::StringRef clElfDir,
772774
AIE::AIEToConfigurationOutputType outputType,
773-
std::string blockwrite_prefix) {
775+
std::string blockwrite_prefix, bool skipCtrlPktOverlay) {
774776
const AIETargetModel &targetModel =
775777
(const AIETargetModel &)device.getTargetModel();
776778

@@ -789,7 +791,7 @@ LogicalResult xilinx::AIE::generateAndInsertConfigOps(
789791

790792
bool generateElfs = true;
791793
if (failed(generateTransactions(ctl, clElfDir, device, aieSim, generateElfs,
792-
true, true)))
794+
true, true, skipCtrlPktOverlay)))
793795
return failure();
794796

795797
// Export the transactions to a binary buffer

lib/Dialect/AIE/Transforms/AIECreatePathFindFlows.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ AIEPathfinderPass::runOnPacketFlow(DeviceOp device, OpBuilder &builder,
282282
DenseMap<PhysPort, BoolAttr> keepPktHeaderAttr;
283283
// Map from tileID and master ports to flags labelling control packet flows
284284
DenseMap<std::pair<PhysPort, int>, bool> ctrlPktFlows;
285+
// Set of master ports that belong to control packet overlay flows
286+
DenseSet<PhysPort> ctrlPktOverlayMasterPorts;
285287

286288
for (auto tileOp : device.getOps<TileOp>()) {
287289
int col = tileOp.colIndex();
@@ -365,9 +367,10 @@ AIEPathfinderPass::runOnPacketFlow(DeviceOp device, OpBuilder &builder,
365367
Port destPort = conn.dst;
366368
auto sourceFlow =
367369
std::make_pair(std::make_pair(tileId, sourcePort), flowID);
368-
if (ctrlPktFlows[{{tileId, destPort}, flowID}])
370+
if (ctrlPktFlows[{{tileId, destPort}, flowID}]) {
369371
ctrlPacketFlows[sourceFlow].push_back({tileId, destPort});
370-
else
372+
ctrlPktOverlayMasterPorts.insert({tileId, destPort});
373+
} else
371374
packetFlows[sourceFlow].push_back({tileId, destPort});
372375
slavePorts.push_back(sourceFlow);
373376
LLVM_DEBUG(llvm::dbgs() << "flowID " << flowID << ':'
@@ -882,9 +885,11 @@ AIEPathfinderPass::runOnPacketFlow(DeviceOp device, OpBuilder &builder,
882885
amsels.push_back(amselOps[msel]);
883886
}
884887

885-
MasterSetOp::create(builder, tileLoc, builder.getIndexType(), bundle,
886-
channel, amsels,
887-
keepPktHeaderAttr[{tileId, tileMaster}]);
888+
auto msOp = MasterSetOp::create(builder, tileLoc, builder.getIndexType(),
889+
bundle, channel, amsels,
890+
keepPktHeaderAttr[{tileId, tileMaster}]);
891+
if (ctrlPktOverlayMasterPorts.contains({tileId, tileMaster}))
892+
msOp->setAttr("is_ctrl_pkt_overlay", builder.getUnitAttr());
888893
}
889894

890895
// Generate the packet rules
@@ -910,11 +915,16 @@ AIEPathfinderPass::runOnPacketFlow(DeviceOp device, OpBuilder &builder,
910915
#endif
911916
Value amsel = amselOps[slaveAMSels[group.front()]];
912917

918+
// Check if this group is a ctrl-pkt overlay flow
919+
bool isCtrlPktGroup = ctrlPacketFlows.count(group.front()) > 0;
920+
913921
PacketRulesOp packetrules;
914922
if (slaveRules.count(slave) == 0) {
915923
packetrules = PacketRulesOp::create(builder, tileLoc, bundle, channel);
916924
PacketRulesOp::ensureTerminator(packetrules.getRules(), builder,
917925
tileLoc);
926+
if (isCtrlPktGroup)
927+
packetrules->setAttr("is_ctrl_pkt_overlay", builder.getUnitAttr());
918928
slaveRules[slave] = packetrules;
919929
} else
920930
packetrules = slaveRules[slave];

0 commit comments

Comments
 (0)