Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[proposal][wip] Add event trace configuration to mlir-aie#2705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
fifield wants to merge41 commits intoXilinx:main
base:main
Choose a base branch
Loading
fromfifield:events_proposal
Draft
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
41 commits
Select commitHold shift + click to select a range
80a48e3
Add a callable library function to parse_trace.py
fifieldNov 13, 2025
733652a
Apply suggestions from code review
fifieldNov 13, 2025
edee5a6
Generate trace_events package with CMake instead of checking into git
fifieldNov 10, 2025
7a7e694
Apply suggestions from code review
fifieldNov 11, 2025
a1cb4cf
Make duplicate event number detection fail the build (#2697)
CopilotNov 11, 2025
e1bfbde
Generate and include tablegen event enums in AIE dialect
fifieldNov 14, 2025
543bedb
Commit 1: Add TableGen definitions for trace operations
fifieldNov 8, 2025
c5e52d5
Commit 2: Add verification tests for trace operations
fifieldNov 8, 2025
7034d74
Commit 3: Implement standalone JSON register database loader
fifieldNov 8, 2025
6c506c6
Commit 4: Implement AIETraceToConfigPass
fifieldNov 8, 2025
c7c734c
Commit 5: Implement AIEInlineTraceConfigPass
fifieldNov 8, 2025
c4c8b5e
Commit 6: Add AIEConfigToNPUPass stub implementation
fifieldNov 8, 2025
a25c6fe
Commit 7: Add end-to-end trace pipeline test
fifieldNov 8, 2025
b4f5660
Complete Pass 3 implementation with RegisterDatabase integration
fifieldNov 8, 2025
b611636
Refactor: Fix design issue with col/row preservation
fifieldNov 8, 2025
248af1c
Move trace NPU passes to AIEX dialect (fixes AIEX loading issue)
fifieldNov 8, 2025
9a4ff28
Move and update trace tests to AIEX dialect
fifieldNov 8, 2025
184c25d
Update AIEX tests to use runtime_sequence
fifieldNov 8, 2025
10449f3
checkpoint
fifieldNov 10, 2025
4a4e41f
start a test
fifieldNov 11, 2025
300908f
format
fifieldNov 11, 2025
6b591cc
checkpoint
fifieldNov 11, 2025
97007eb
updates, fixes, formatting
fifieldNov 12, 2025
caaf7f4
clang-format
fifieldNov 12, 2025
b58edf2
remove aie-config-to-npu placeholder
fifieldNov 12, 2025
6556d01
fixes for core mem events
fifieldNov 12, 2025
1635816
fix test location
fifieldNov 12, 2025
aa79764
Add stream switch port event monitoring to AIE trace infrastructure
fifieldNov 13, 2025
41ba2c7
update example to use aie.trace.port
fifieldNov 13, 2025
bb18de2
Replace BoolAttr with DMAChannelDir for trace port direction
fifieldNov 13, 2025
ebfab0d
Add test.py for trace example
fifieldNov 13, 2025
6095f3a
implement trace and combo event op tablegen
fifieldNov 14, 2025
7907894
Update lower pass for combo and edge events
fifieldNov 14, 2025
01c9a32
Update dialect to use generated enums for events
fifieldNov 15, 2025
a2433db
fix aie1 suffix
fifieldNov 15, 2025
e6a6457
checkpoint
fifieldNov 15, 2025
2532c8a
fixes, format, refactor, cleanup
fifieldNov 15, 2025
2e0fc12
checkpoint
fifieldNov 15, 2025
ef6c53e
wip
fifieldNov 16, 2025
cc56b4d
cleanup, fixes, refactor
fifieldNov 17, 2025
fc99d49
implement AIETargetModel getStreamSwitchPortIndex
fifieldNov 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
fixes for core mem events
  • Loading branch information
@fifield
fifield committedNov 14, 2025
commit6556d01297745d1c174d8c283c9fda8b4f1b86ff
5 changes: 3 additions & 2 deletionsinclude/aie/Dialect/AIE/IR/AIETraceOps.td
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -255,13 +255,14 @@ def AIE_TraceConfigOp : AIE_Op<"trace.config", [

let arguments = (ins
Index:$tile,
SymbolNameAttr:$sym_name
SymbolNameAttr:$sym_name,
OptionalAttr<TracePacketTypeAttr>:$packet_type
);

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

let assemblyFormat = [{
$sym_name `(` $tile `)` $body attr-dict
$sym_name `(` $tile `)`(`packet_type` `=` $packet_type^)?$body attr-dict
}];
}

Expand Down
20 changes: 16 additions & 4 deletionslib/Dialect/AIE/Transforms/AIETraceToConfig.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -42,16 +42,28 @@ struct AIETraceToConfigPass : AIETraceToConfigBase<AIETraceToConfigPass> {
std::string configName = (trace.getSymName().str() + "_config");
auto tile = cast<TileOp>(trace.getTile().getDefiningOp());

// Find packet type (if any)
TracePacketType packetType = TracePacketType::Core; // default
for (auto &op : trace.getBody().getOps()) {
if (auto packetOp = dyn_cast<TracePacketOp>(op)) {
packetType = packetOp.getType();
break;
}
}

// Insert trace.config after trace declaration
builder.setInsertionPointAfter(trace);
auto configOp = builder.create<TraceConfigOp>(
trace.getLoc(), trace.getTile(), builder.getStringAttr(configName));
trace.getLoc(), trace.getTile(), builder.getStringAttr(configName),
TracePacketTypeAttr::get(builder.getContext(), packetType));

// Build register writes inside config body
Block *configBody = new Block();
configOp.getBody().push_back(configBody);
OpBuilder configBuilder = OpBuilder::atBlockEnd(configBody);

bool isMem = (packetType == TracePacketType::Mem);

// 1. Emit Trace_Control0 fields
// Check for start/stop events
for (auto &op : trace.getBody().getOps()) {
Expand All@@ -62,7 +74,7 @@ struct AIETraceToConfigPass : AIETraceToConfigBase<AIETraceToConfigPass> {
} else if (auto eventAttr = startOp.getEvent()) {
// Look up event number from database
std::string eventName = eventAttr->getName().str();
auto eventNum = regDB->lookupEvent(eventName, tile);
auto eventNum = regDB->lookupEvent(eventName, tile, isMem);
if (eventNum) {
startEvent = *eventNum;
} else {
Expand All@@ -85,7 +97,7 @@ struct AIETraceToConfigPass : AIETraceToConfigBase<AIETraceToConfigPass> {
} else if (auto eventAttr = stopOp.getEvent()) {
// Look up event number from database
std::string eventName = eventAttr->getName().str();
auto eventNum = regDB->lookupEvent(eventName, tile);
auto eventNum = regDB->lookupEvent(eventName, tile, isMem);
if (eventNum) {
stopEvent = *eventNum;
} else {
Expand DownExpand Up@@ -140,7 +152,7 @@ struct AIETraceToConfigPass : AIETraceToConfigBase<AIETraceToConfigPass> {
std::string eventName = events[i].getEvent().getName().str();

// Look up event number from database
auto eventNum = regDB->lookupEvent(eventName, tile);
auto eventNum = regDB->lookupEvent(eventName, tile, isMem);
if (!eventNum) {
trace.emitWarning("Unknown event: ") << eventName;
continue;
Expand Down
8 changes: 7 additions & 1 deletionlib/Dialect/AIEX/Transforms/AIEInlineTraceConfig.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,6 +67,12 @@ struct AIEInlineTraceConfigPass
int col = tileOp.getCol();
int row = tileOp.getRow();

// Determine if we're accessing memory module from packet type
bool isMem = false;
if (configOp.getPacketType()) {
isMem = (*configOp.getPacketType() == TracePacketType::Mem);
}

// Process all trace.reg operations in the config
for (auto &op : configOp.getBody().getOps()) {
auto regOp = dyn_cast<TraceRegOp>(op);
Expand All@@ -83,7 +89,7 @@ struct AIEInlineTraceConfigPass
// Look up register to get offset
auto regName = regOp.getRegName().str();
const RegisterInfo *regInfo =
regDb->lookupRegister(regName, tileOp,/*isMem=*/false);
regDb->lookupRegister(regName, tileOp, isMem);
if (!regInfo) {
regOp.emitError("Register '") << regName << "' not found for tile ("
<< col << ", " << row << ")";
Expand Down
162 changes: 152 additions & 10 deletionsmlir_trace_example/QUICKSTART.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,10 +21,16 @@ make -j$(nproc)
# Run the design (if you have NPU hardware)
make run

# Run with trace enabled
# Run with trace enabled (uses aie_new_trace.mlir by default)
make trace

# Or run with the new declarative trace explicitly
make run_new_trace
```

**Note:** The default `make trace` now uses the declarative syntax (`aie_new_trace.mlir`).
For the legacy low-level syntax, see `aie_trace.mlir`.

## Trace Output

After running `make trace`, you'll get:
Expand All@@ -43,9 +49,6 @@ The **trace_timeline.png** provides a visual representation of:

Open `trace_timeline.png` in any image viewer to see the timeline visualization.

## Understanding the Design
```

## Understanding the Design

The example implements: **Output[i] = Input[i] × ScaleFactor**
Expand All@@ -59,11 +62,85 @@ The computation is split across 4 sub-vectors of 1024 elements each, processed b
## Key Files to Study

1. **Start here:** `aie_no_trace.mlir` - Basic design without trace
2. **Then compare:** `aie_trace.mlir` - Same design with trace added
3. **Run diff:** `diff -u aie_no_trace.mlir aie_trace.mlir | less`
2. **Declarative syntax:** `aie_new_trace.mlir` - Design with high-level trace declarations (recommended)
3. **Low-level example:** `aie_trace.mlir` - Same design with explicit register writes
4. **Compare approaches:**
- `diff -u aie_no_trace.mlir aie_new_trace.mlir | less` - See high-level trace additions
- `diff -u aie_new_trace.mlir aie_trace.mlir | less` - Compare declarative vs low-level

## Two Ways to Configure Trace

### New Declarative Syntax (Recommended)

The `aie_new_trace.mlir` file uses high-level trace declarations that are easier to read and maintain:

```mlir
aie.trace(%tile_0_2) {
aie.trace.mode event_time
aie.trace.start_event <INSTR_EVENT_0>
aie.trace.stop_event <INSTR_EVENT_1>
aie.trace.packet_id 1
aie.trace.packet_type core
aie.trace.event <INSTR_EVENT_0> slot=0
aie.trace.event <INSTR_EVENT_1> slot=1
// ... more events
}
```

This gets automatically lowered to register writes by the compiler passes:
- `-aie-trace-to-config` - Converts to trace.config operations
- `-aie-trace-pack-reg-writes` - Optimizes register writes
- `-aiex-inline-trace-config` - Generates final npu.write32 operations

### Legacy Low-Level Syntax

The `aie_trace.mlir` file uses explicit register writes (still supported but verbose):

```mlir
aiex.npu.write32 {address = 213200 : ui32, column = 0 : i32,
row = 2 : i32, value = 2038038528 : ui32}
```

**Recommendation:** Use the declarative syntax in `aie_new_trace.mlir` as your starting point.

## Trace Components in MLIR

### Declarative Trace (aie_new_trace.mlir)

The new syntax uses intuitive trace declarations:

```mlir
aie.trace(%tile_0_2) {
// Set trace mode (event_time, event_pc, or execution)
aie.trace.mode event_time

// Define start/stop conditions
aie.trace.start_event <INSTR_EVENT_0>
aie.trace.stop_event <INSTR_EVENT_1>

// Packet routing configuration
aie.trace.packet_id 1
aie.trace.packet_type core

// Events to capture (up to 8 slots)
aie.trace.event <INSTR_EVENT_0> slot=0
aie.trace.event <INSTR_EVENT_1> slot=1
aie.trace.event <INSTR_VECTOR> slot=2
// ... more events
}
```

The compiler automatically:
- Validates event names against the architecture database
- Checks that events are valid for the tile type (core/shim/mem)
- Encodes events into register values
- Optimizes multiple field writes into single register writes
- Generates the appropriate npu.write32 operations

### Low-Level Components (aie_trace.mlir)

For reference, the low-level implementation uses:

### 1. Packet Flows (lines 70-80)
Routes trace packets from tiles to shim DMA:
```mlir
Expand DownExpand Up@@ -114,6 +191,46 @@ The trace shows:

## Modifying the Example

### Using Declarative Syntax (Recommended)

**Change traced events:**
Edit the `aie.trace` block in `aie_new_trace.mlir`:
```mlir
aie.trace(%tile_0_2) {
// ... existing config ...
aie.trace.event <LOCK_STALL> slot=4 // Add lock stall events
aie.trace.event <MEMORY_STALL> slot=5 // Add memory stall events
}
```

**Trace multiple tiles:**
Add more trace blocks:
```mlir
aie.trace(%tile_0_3) {
aie.trace.mode event_time
aie.trace.start_event <INSTR_EVENT_0>
aie.trace.stop_event <INSTR_EVENT_1>
aie.trace.packet_id 3 // Different packet ID
aie.trace.packet_type core
aie.trace.event <INSTR_EVENT_0> slot=0
}
```

**Change trace mode:**
```mlir
aie.trace(%tile_0_2) {
aie.trace.mode event_pc // Capture program counter instead of time
// ... rest of config
}
```

**Available events by tile type:**
- Core tiles: `INSTR_EVENT_0`, `INSTR_EVENT_1`, `INSTR_VECTOR`, `MEMORY_STALL`, `LOCK_STALL`, etc.
- Shim tiles: `DMA_S2MM_0_START_TASK`, `DMA_MM2S_0_START_TASK`, `DMA_S2MM_0_STREAM_STARVATION`, etc.
- Mem tiles: Check `utils/events_database.json` for complete list

### Using Low-Level Syntax (Advanced)

### Change trace buffer size:
Edit line 131 in `aie_trace.mlir`:
```mlir
Expand DownExpand Up@@ -150,14 +267,39 @@ Modify register values at lines 105-110 (see NPU documentation for event codes)

## Next Steps

1. **Study the code:** Compare `aie_no_trace.mlir` vs `aie_trace.mlir`
2. **Modify events:** Change which events are traced
3. **Add tiles:** Trace multiple compute tiles
4. **Analyze output:** Study the JSON trace file
1. **Study the code:**
- Start with `aie_new_trace.mlir` to see declarative trace syntax
- Compare with `aie_no_trace.mlir` to see what trace adds
- Examine `aie_trace.mlir` to understand low-level implementation
2. **Modify events:** Add different events to the trace configuration
3. **Add tiles:** Trace multiple compute tiles simultaneously
4. **Analyze output:** Study the JSON trace file and timeline visualization
5. **Optimize:** Use trace data to find performance bottlenecks

## Compiler Pass Pipeline

When using declarative syntax, the compiler applies these passes:

1. **`-aie-trace-to-config`** - Converts `aie.trace` blocks to `aie.trace.config` with register operations
2. **`-aie-trace-pack-reg-writes`** - Optimizes by merging multiple field writes into single register writes
3. **`-aiex-inline-trace-config`** - Generates final `aiex.npu.write32` operations in runtime sequence

You can see the intermediate steps:
```bash
# After conversion to config
aie-opt -aie-trace-to-config aie_new_trace.mlir

# After register packing optimization
aie-opt -aie-trace-to-config -aie-trace-pack-reg-writes aie_new_trace.mlir

# Final lowering (what actually runs)
aie-opt -aie-trace-to-config -aie-trace-pack-reg-writes -aiex-inline-trace-config aie_new_trace.mlir
```

## Related Documentation

- [Programming Guide Section 4b](../programming_guide/section-4/section-4b) - Python trace examples
- [README.md](./README.md) - Detailed explanation of trace components
- [AGENTS.md](../AGENTS.md) - Guide for LLM agents working with trace code
- [AIE Architecture Manual] - Hardware trace unit documentation
- `utils/events_database.json` - Complete list of available trace events by architecture
Loading

[8]ページ先頭

©2009-2025 Movatter.jp