Skip to content

Commit 3a1aba2

Browse files
yenjamesclaudejgmelber
authored
Insert trace flows pass (#2962)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Joseph Melber <jgmelber@gmail.com>
1 parent c019e63 commit 3a1aba2

24 files changed

Lines changed: 1774 additions & 413 deletions

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,22 @@ def EdgeTriggerAttr : I32EnumAttr<"EdgeTrigger",
159159
}];
160160
}
161161

162+
//===----------------------------------------------------------------------===//
163+
// Trace Shim Routing Strategy Enumeration
164+
//===----------------------------------------------------------------------===//
165+
166+
def TraceShimRoutingSingle : I32EnumAttrCase<"Single", 0, "single">;
167+
168+
def TraceShimRoutingAttr : I32EnumAttr<"TraceShimRouting",
169+
"Shim tile routing strategy for trace collection",
170+
[
171+
TraceShimRoutingSingle
172+
]> {
173+
let cppNamespace = "::xilinx::AIE";
174+
let description = [{
175+
Determines how traces are routed to shim tiles:
176+
- single: All traces route to a single shim tile (column 0)
177+
}];
178+
}
179+
162180
#endif // AIE_TRACE_ATTRS

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

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,13 @@ def AIE_TraceOp : AIE_Op<"trace", [
5454

5555
let arguments = (ins
5656
Index:$tile,
57-
SymbolNameAttr:$sym_name,
58-
OptionalAttr<AIEI32Attr>:$buffer_size
57+
SymbolNameAttr:$sym_name
5958
);
6059

6160
let regions = (region SizedRegion<1>:$body);
6261

6362
let assemblyFormat = [{
64-
$sym_name `(` $tile `)` (`buffer_size` `=` $buffer_size^)?
65-
$body attr-dict
63+
$sym_name `(` $tile `)` $body attr-dict
6664
}];
6765

6866
let hasVerifier = 1;
@@ -464,6 +462,47 @@ def AIE_TraceEdgeEventOp : AIE_Op<"trace.edge_event", [
464462
let hasVerifier = 1;
465463
}
466464

465+
//===----------------------------------------------------------------------===//
466+
// AIE_TraceHostConfigOp - Host Buffer Configuration
467+
//===----------------------------------------------------------------------===//
468+
469+
def AIE_TraceHostConfigOp : AIE_Op<"trace.host_config", [
470+
HasParent<"RuntimeSequenceOp">
471+
]> {
472+
let summary = "Configure host buffer for trace data collection";
473+
474+
let description = [{
475+
Configures host-side trace buffer.
476+
477+
Attributes:
478+
- buffer_size: Trace buffer size in bytes
479+
- arg_idx (default=4): XRT argument index for trace buffer
480+
- routing (default=single): Shim routing strategy. Currently only 'single'
481+
is supported, which routes all traces to column 0's shim.
482+
- trace_after_last_tensor (default=false): Append trace data to the last
483+
tensor argument in the runtime_sequence. When true, buffer_offset is computed
484+
from the tensor size. Only valid with routing=single.
485+
486+
Example:
487+
```mlir
488+
aie.runtime_sequence(%arg0: memref<16xi32>) {
489+
aie.trace.host_config buffer_size=65536
490+
aie.trace.start_config @trace1
491+
}
492+
```
493+
}];
494+
495+
let arguments = (ins
496+
AIEI32Attr:$buffer_size,
497+
DefaultValuedAttr<AIEI32Attr, "4">:$arg_idx,
498+
DefaultValuedAttr<TraceShimRoutingAttr, "TraceShimRouting::Single">:$routing,
499+
DefaultValuedAttr<BoolAttr, "false">:$trace_after_last_tensor
500+
);
501+
502+
let hasCustomAssemblyFormat = 1;
503+
let hasVerifier = 1;
504+
}
505+
467506
//===----------------------------------------------------------------------===//
468507
// AIE_TraceStartConfigOp - Runtime Configuration Invocation
469508
//===----------------------------------------------------------------------===//

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIEAssignTileCtrlIDsPass();
6868
std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIETraceToConfigPass();
6969
std::unique_ptr<mlir::OperationPass<DeviceOp>>
7070
createAIETraceRegPackWritesPass();
71+
std::unique_ptr<mlir::OperationPass<DeviceOp>> createAIEInsertTraceFlowsPass();
7172

7273
/// Generate the code for registering passes.
7374
#define GEN_PASS_REGISTRATION

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,4 +424,41 @@ def AIETraceRegPackWrites : Pass<"aie-trace-pack-reg-writes", "DeviceOp"> {
424424
];
425425
}
426426

427+
def AIEInsertTraceFlows : Pass<"aie-insert-trace-flows", "DeviceOp"> {
428+
let summary = "Insert packet flows and runtime sequence trace setup";
429+
let description = [{
430+
For each aie.trace operation, this pass:
431+
- Creates ONE packet flow from trace port to shim DMA
432+
- Groups traces by target shim (minimizes shim usage, ideally 1)
433+
- Inserts ONE shim buffer descriptor per shim tile for all traces
434+
- Inserts per-tile timer control register writes
435+
- Inserts per-shim broadcast and DMA control setup
436+
437+
All trace configuration is injected at the beginning of the runtime
438+
sequence, before user data transfer operations.
439+
440+
Multiple trace streams (from different tiles or different trace units
441+
on the same tile) are routed to the same shim DMA channel and drained
442+
by a single buffer descriptor.
443+
}];
444+
445+
let constructor = "xilinx::AIE::createAIEInsertTraceFlowsPass()";
446+
447+
let dependentDialects = [
448+
"xilinx::AIE::AIEDialect",
449+
"xilinx::AIEX::AIEXDialect",
450+
];
451+
452+
let options = [
453+
Option<"clShimChannel", "shim-channel", "int", "1",
454+
"S2MM DMA channel to use for trace (default: 1)">,
455+
Option<"clDefaultBdId", "default-bd-id", "int", "15",
456+
"Buffer descriptor ID for trace (default: 15)">,
457+
Option<"clPacketIdStart", "packet-id-start", "int", "1",
458+
"Starting packet ID for trace flows (default: 1)">,
459+
Option<"clTraceBurstLength", "burst-length", "int", "64",
460+
"DMA burst length for trace transfers (default: 64 bytes)">
461+
];
462+
}
463+
427464
#endif

lib/Dialect/AIE/IR/AIETraceOps.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,111 @@ ParseResult TraceEdgeEventOp::parse(OpAsmParser &parser,
727727
return success();
728728
}
729729

730+
//===----------------------------------------------------------------------===//
731+
// TraceHostConfigOp
732+
//===----------------------------------------------------------------------===//
733+
734+
void TraceHostConfigOp::print(OpAsmPrinter &p) {
735+
p << " buffer_size = " << getBufferSize();
736+
737+
// Only print non-default values
738+
if (getArgIdx() != 4)
739+
p << " arg_idx = " << getArgIdx();
740+
741+
if (getRouting() != TraceShimRouting::Single)
742+
p << " routing = " << stringifyTraceShimRouting(getRouting());
743+
744+
if (getTraceAfterLastTensor())
745+
p << " trace_after_last_tensor = true";
746+
747+
p.printOptionalAttrDict((*this)->getAttrs(),
748+
/*elidedAttrs=*/{"buffer_size", "arg_idx", "routing",
749+
"trace_after_last_tensor"});
750+
}
751+
752+
ParseResult TraceHostConfigOp::parse(OpAsmParser &parser,
753+
OperationState &result) {
754+
// Parse required buffer_size
755+
IntegerAttr bufferSize;
756+
if (parser.parseKeyword("buffer_size") || parser.parseEqual() ||
757+
parser.parseAttribute(bufferSize, parser.getBuilder().getI32Type(),
758+
"buffer_size", result.attributes))
759+
return failure();
760+
761+
// Parse arg_idx (default: 4)
762+
int32_t argIdxVal = 4;
763+
if (succeeded(parser.parseOptionalKeyword("arg_idx"))) {
764+
IntegerAttr argIdx;
765+
if (parser.parseEqual() ||
766+
parser.parseAttribute(argIdx, parser.getBuilder().getI32Type(),
767+
"arg_idx", result.attributes))
768+
return failure();
769+
} else {
770+
result.attributes.set("arg_idx",
771+
parser.getBuilder().getI32IntegerAttr(argIdxVal));
772+
}
773+
774+
// Parse routing (default: single)
775+
TraceShimRouting routingVal = TraceShimRouting::Single;
776+
if (succeeded(parser.parseOptionalKeyword("routing"))) {
777+
if (parser.parseEqual())
778+
return failure();
779+
StringRef routingStr;
780+
if (failed(parser.parseKeyword(&routingStr)))
781+
return failure();
782+
auto routing = symbolizeTraceShimRouting(routingStr);
783+
if (!routing)
784+
return parser.emitError(parser.getCurrentLocation(),
785+
"unknown routing strategy: ")
786+
<< routingStr;
787+
routingVal = *routing;
788+
}
789+
result.attributes.set(
790+
"routing", TraceShimRoutingAttr::get(parser.getContext(), routingVal));
791+
792+
// Parse trace_after_last_tensor (default: false)
793+
bool traceAfterVal = false;
794+
if (succeeded(parser.parseOptionalKeyword("trace_after_last_tensor"))) {
795+
if (parser.parseEqual())
796+
return failure();
797+
StringRef boolStr;
798+
if (failed(parser.parseKeyword(&boolStr)))
799+
return failure();
800+
if (boolStr == "true")
801+
traceAfterVal = true;
802+
else if (boolStr != "false")
803+
return parser.emitError(parser.getCurrentLocation(),
804+
"expected 'true' or 'false'");
805+
}
806+
result.attributes.set("trace_after_last_tensor",
807+
parser.getBuilder().getBoolAttr(traceAfterVal));
808+
809+
if (parser.parseOptionalAttrDict(result.attributes))
810+
return failure();
811+
812+
return success();
813+
}
814+
815+
LogicalResult TraceHostConfigOp::verify() {
816+
bool useTraceAfterLastTensor = getTraceAfterLastTensor();
817+
818+
// Appending trace data after the last tensor only works with single shim
819+
if (useTraceAfterLastTensor) {
820+
if (getRouting() != TraceShimRouting::Single) {
821+
return emitOpError("appending trace data to the last tensor argument "
822+
"only works with single shim destination strategy "
823+
"(routing=single)");
824+
}
825+
}
826+
827+
// Validate buffer_size is positive
828+
if (getBufferSize() <= 0) {
829+
return emitOpError("buffer_size must be positive");
830+
}
831+
832+
return success();
833+
}
834+
730835
//===----------------------------------------------------------------------===//
731836
// TraceStartConfigOp
732837
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)