16#include "mlir/IR/Attributes.h"
17#include "mlir/Pass/Pass.h"
20#define GEN_PASS_DEF_AIETRACETOCONFIG
21#define GEN_PASS_DEF_AIETRACEREGPACKWRITES
22#include "aie/Dialect/AIE/Transforms/AIEPasses.h.inc"
31struct AIETraceToConfigPass
32 : xilinx::AIE::impl::AIETraceToConfigBase<AIETraceToConfigPass> {
33 void runOnOperation()
override {
34 DeviceOp device = getOperation();
35 OpBuilder builder(device);
36 const auto &targetModel = device.getTargetModel();
39 SmallVector<TraceOp> traces;
40 device.walk([&](TraceOp trace) { traces.push_back(trace); });
42 for (
auto trace : traces) {
44 std::string configName = (trace.getSymName().str() +
"_config");
45 auto tile = cast<TileOp>(trace.getTile().getDefiningOp());
46 TileID tileID = tile.getTileID();
49 TracePacketType packetType = TracePacketType::Core;
50 for (
auto &op : trace.getBody().getOps()) {
51 if (
auto packetOp = dyn_cast<TracePacketOp>(op)) {
52 packetType = packetOp.getType();
58 builder.setInsertionPointAfter(trace);
59 auto configOp = builder.create<TraceConfigOp>(
60 trace.getLoc(), trace.getTile(), builder.getStringAttr(configName),
61 TracePacketTypeAttr::get(builder.getContext(), packetType));
64 Block *configBody =
new Block();
65 configOp.getBody().push_back(configBody);
66 OpBuilder configBuilder = OpBuilder::atBlockEnd(configBody);
68 bool isMem = (packetType == TracePacketType::Mem);
75 for (
auto &op : trace.getBody().getOps()) {
76 if (
auto comboOp = dyn_cast<TraceComboEventOp>(op)) {
77 uint32_t slot = comboOp.getSlot();
80 std::string eventAName = comboOp.getEventA().getEventName();
81 std::string eventBName = comboOp.getEventB().getEventName();
82 ComboLogic logic = comboOp.getLogic();
85 std::optional<uint32_t> eventANum, eventBNum;
87 if (
auto enumValA = comboOp.getEventA().getEnumValue()) {
88 eventANum =
static_cast<uint32_t
>(*enumValA);
90 eventANum = targetModel.lookupEvent(eventAName, tileID, isMem);
93 if (
auto enumValB = comboOp.getEventB().getEnumValue()) {
94 eventBNum =
static_cast<uint32_t
>(*enumValB);
96 eventBNum = targetModel.lookupEvent(eventBName, tileID, isMem);
100 comboOp.emitError(
"unknown trace event '") << eventAName <<
"'";
101 return signalPassFailure();
104 comboOp.emitError(
"unknown trace event '") << eventBName <<
"'";
105 return signalPassFailure();
109 StringRef eventAField, eventBField, controlField;
111 eventAField =
"eventA";
112 eventBField =
"eventB";
113 controlField =
"combo0";
114 }
else if (slot == 1) {
115 eventAField =
"eventC";
116 eventBField =
"eventD";
117 controlField =
"combo1";
118 }
else if (slot == 2) {
121 eventAField =
"eventA";
122 eventBField =
"eventB";
123 controlField =
"combo2";
127 configBuilder.create<TraceRegOp>(
128 comboOp.getLoc(), builder.getStringAttr(
"Combo_event_inputs"),
129 builder.getStringAttr(eventAField), comboOp.getEventA(),
131 builder.getStringAttr(
"combo" + std::to_string(slot) +
134 configBuilder.create<TraceRegOp>(
135 comboOp.getLoc(), builder.getStringAttr(
"Combo_event_inputs"),
136 builder.getStringAttr(eventBField), comboOp.getEventB(),
138 builder.getStringAttr(
"combo" + std::to_string(slot) +
142 configBuilder.create<TraceRegOp>(
143 comboOp.getLoc(), builder.getStringAttr(
"Combo_event_control"),
144 builder.getStringAttr(controlField),
145 builder.getI32IntegerAttr(
static_cast<uint32_t
>(logic)),
147 builder.getStringAttr(
"combo" + std::to_string(slot) +
" logic"));
152 for (
auto &op : trace.getBody().getOps()) {
153 if (
auto edgeOp = dyn_cast<TraceEdgeEventOp>(op)) {
154 uint32_t slot = edgeOp.getSlot();
155 std::string eventName = edgeOp.getEvent().getEventName();
156 EdgeTrigger trigger = edgeOp.getTrigger();
159 std::optional<uint32_t> eventNum;
161 if (
auto enumVal = edgeOp.getEvent().getEnumValue()) {
162 eventNum =
static_cast<uint32_t
>(*enumVal);
164 eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
168 edgeOp.emitError(
"unknown trace event '") << eventName <<
"'";
169 return signalPassFailure();
173 StringRef eventField =
174 (slot == 0) ?
"Edge_Detection_Event_0" :
"Edge_Detection_Event_1";
175 StringRef risingField = (slot == 0)
176 ?
"Edge_Detection_0_Trigger_Rising"
177 :
"Edge_Detection_1_Trigger_Rising";
178 StringRef fallingField = (slot == 0)
179 ?
"Edge_Detection_0_Trigger_Falling"
180 :
"Edge_Detection_1_Trigger_Falling";
183 configBuilder.create<TraceRegOp>(
185 builder.getStringAttr(
"Edge_Detection_event_control"),
186 builder.getStringAttr(eventField), edgeOp.getEvent(),
188 builder.getStringAttr(
"edge" + std::to_string(slot) +
" source"));
192 (trigger == EdgeTrigger::RISING || trigger == EdgeTrigger::BOTH);
194 (trigger == EdgeTrigger::FALLING || trigger == EdgeTrigger::BOTH);
196 configBuilder.create<TraceRegOp>(
198 builder.getStringAttr(
"Edge_Detection_event_control"),
199 builder.getStringAttr(risingField),
200 builder.getI32IntegerAttr(rising ? 1 : 0),
202 builder.getStringAttr(
"edge" + std::to_string(slot) +
" rising"));
204 configBuilder.create<TraceRegOp>(
206 builder.getStringAttr(
"Edge_Detection_event_control"),
207 builder.getStringAttr(fallingField),
208 builder.getI32IntegerAttr(falling ? 1 : 0),
210 builder.getStringAttr(
"edge" + std::to_string(slot) +
217 for (
auto &op : trace.getBody().getOps()) {
218 if (
auto startOp = dyn_cast<TraceStartEventOp>(op)) {
219 uint32_t startEvent = 0;
220 if (startOp.getBroadcast()) {
221 uint32_t broadcastNum = *startOp.getBroadcast();
223 std::string eventName;
224 if (tile.isShimTile()) {
225 eventName =
"BROADCAST_A_" + std::to_string(broadcastNum);
227 eventName =
"BROADCAST_" + std::to_string(broadcastNum);
229 auto eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
231 startEvent = *eventNum;
233 startOp.emitError(
"unknown broadcast event '")
235 return signalPassFailure();
237 }
else if (
auto eventAttr = startOp.getEvent()) {
239 std::string eventName = eventAttr->getEventName();
241 std::optional<uint32_t> eventNum;
242 if (
auto enumVal = eventAttr->getEnumValue()) {
243 eventNum =
static_cast<uint32_t
>(*enumVal);
245 eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
249 startEvent = *eventNum;
251 startOp.emitError(
"unknown trace event '") << eventName <<
"'";
252 return signalPassFailure();
256 configBuilder.create<TraceRegOp>(
257 trace.getLoc(), builder.getStringAttr(
"Trace_Control0"),
258 builder.getStringAttr(
"Trace_Start_Event"),
259 builder.getI32IntegerAttr(startEvent),
260 nullptr, builder.getStringAttr(
"start event"));
263 if (
auto stopOp = dyn_cast<TraceStopEventOp>(op)) {
264 uint32_t stopEvent = 0;
265 if (stopOp.getBroadcast()) {
266 uint32_t broadcastNum = *stopOp.getBroadcast();
268 std::string eventName;
269 if (tile.isShimTile()) {
270 eventName =
"BROADCAST_A_" + std::to_string(broadcastNum);
272 eventName =
"BROADCAST_" + std::to_string(broadcastNum);
274 auto eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
276 stopEvent = *eventNum;
278 stopOp.emitError(
"unknown broadcast event '") << eventName <<
"'";
279 return signalPassFailure();
281 }
else if (
auto eventAttr = stopOp.getEvent()) {
283 std::string eventName = eventAttr->getEventName();
285 std::optional<uint32_t> eventNum;
286 if (
auto enumVal = eventAttr->getEnumValue()) {
287 eventNum =
static_cast<uint32_t
>(*enumVal);
289 eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
293 stopEvent = *eventNum;
295 stopOp.emitError(
"unknown trace event '") << eventName <<
"'";
296 return signalPassFailure();
300 configBuilder.create<TraceRegOp>(
301 trace.getLoc(), builder.getStringAttr(
"Trace_Control0"),
302 builder.getStringAttr(
"Trace_Stop_Event"),
303 builder.getI32IntegerAttr(stopEvent),
304 nullptr, builder.getStringAttr(
"stop event"));
310 bool isCore = (packetType == TracePacketType::Core);
311 if (
auto modeOp = dyn_cast<TraceModeOp>(op); modeOp && isCore) {
312 configBuilder.create<TraceRegOp>(
313 trace.getLoc(), builder.getStringAttr(
"Trace_Control0"),
314 builder.getStringAttr(
"Mode"),
315 builder.getI32IntegerAttr(
316 static_cast<uint32_t
>(modeOp.getMode())),
317 nullptr, builder.getStringAttr(
"trace mode"));
321 if (
auto packetOp = dyn_cast<TracePacketOp>(op)) {
322 configBuilder.create<TraceRegOp>(
323 trace.getLoc(), builder.getStringAttr(
"Trace_Control1"),
324 builder.getStringAttr(
"ID"),
325 builder.getI32IntegerAttr(packetOp.getId()),
326 nullptr, builder.getStringAttr(
"packet ID"));
328 configBuilder.create<TraceRegOp>(
329 trace.getLoc(), builder.getStringAttr(
"Trace_Control1"),
330 builder.getStringAttr(
"Packet_Type"),
331 builder.getI32IntegerAttr(
332 static_cast<uint32_t
>(packetOp.getType())),
333 nullptr, builder.getStringAttr(
"packet type"));
338 for (
auto &op : trace.getBody().getOps()) {
339 if (
auto portOp = dyn_cast<TracePortOp>(op)) {
340 uint32_t slot = portOp.getSlot();
343 StringRef registerName = (slot < 4)
344 ?
"Stream_Switch_Event_Port_Selection_0"
345 :
"Stream_Switch_Event_Port_Selection_1";
348 std::string idFieldName =
"Port_" + std::to_string(slot) +
"_ID";
349 std::string masterSlaveFieldName =
350 "Port_" + std::to_string(slot) +
"_Master_Slave";
353 std::string portValue = stringifyWireBundle(portOp.getPort()).str() +
354 ":" + std::to_string(portOp.getChannel());
357 int masterSlaveValue =
358 (portOp.getDirection() == DMAChannelDir::S2MM) ? 1 : 0;
361 configBuilder.create<TraceRegOp>(
362 portOp.getLoc(), builder.getStringAttr(registerName),
363 builder.getStringAttr(idFieldName),
364 builder.getStringAttr(portValue),
366 builder.getStringAttr(
"port " + std::to_string(slot) +
" ID"));
369 configBuilder.create<TraceRegOp>(
370 portOp.getLoc(), builder.getStringAttr(registerName),
371 builder.getStringAttr(masterSlaveFieldName),
372 builder.getI32IntegerAttr(masterSlaveValue),
374 builder.getStringAttr(
"port " + std::to_string(slot) +
380 SmallVector<TraceEventOp> events;
381 for (
auto &op : trace.getBody().getOps()) {
382 if (
auto eventOp = dyn_cast<TraceEventOp>(op)) {
383 events.push_back(eventOp);
387 for (
size_t i = 0; i < events.size() && i < 8; ++i) {
388 std::string eventName = events[i].getEvent().getEventName();
391 std::optional<uint32_t> eventNum;
393 if (
auto enumVal = events[i].getEvent().getEnumValue()) {
394 eventNum =
static_cast<uint32_t
>(*enumVal);
396 eventNum = targetModel.lookupEvent(eventName, tileID, isMem);
400 events[i].emitError(
"unknown trace event '") << eventName <<
"'";
401 return signalPassFailure();
405 StringRef registerName = (i < 4) ?
"Trace_Event0" :
"Trace_Event1";
406 std::string fieldName =
"Trace_Event" + std::to_string(i);
409 configBuilder.create<TraceRegOp>(
410 trace.getLoc(), builder.getStringAttr(registerName),
411 builder.getStringAttr(fieldName),
412 events[i].getEvent(),
413 nullptr, builder.getStringAttr(eventName));
417 configBuilder.create<EndOp>(trace.getLoc());
420 device.walk([&](TraceStartConfigOp startConfig) {
421 if (startConfig.getTraceConfig() == trace.getSymName()) {
422 startConfig.setTraceConfigAttr(
423 SymbolRefAttr::get(builder.getContext(), configName));
435std::unique_ptr<OperationPass<DeviceOp>>
437 return std::make_unique<AIETraceToConfigPass>();
446struct AIETraceRegPackWritesPass
447 : xilinx::AIE::impl::AIETraceRegPackWritesBase<AIETraceRegPackWritesPass> {
448 void runOnOperation()
override {
449 DeviceOp device = getOperation();
450 const auto &targetModel = device.getTargetModel();
453 device.walk([&](TraceConfigOp configOp) {
455 auto tile = cast<TileOp>(configOp.getTile().getDefiningOp());
459 if (
auto packetType = configOp.getPacketType()) {
460 isMem = (*packetType == TracePacketType::Mem);
464 SmallVector<TraceRegOp> regsToConvert;
465 for (
auto &op : configOp.getBody().front()) {
466 if (
auto regOp = dyn_cast<TraceRegOp>(op)) {
467 if (regOp.getField() && !regOp.getMask()) {
468 regsToConvert.push_back(regOp);
473 OpBuilder builder(&configOp.getBody().front(),
474 configOp.getBody().front().begin());
476 TileID tileID = tile.getTileID();
477 for (
auto regOp : regsToConvert) {
480 targetModel.lookupRegister(regOp.getRegName(), tileID, isMem);
483 regOp.emitError(
"Register not found in database: ")
484 << regOp.getRegName();
485 return signalPassFailure();
490 regOp.emitError(
"Field not found in register: ")
491 << *regOp.getField() <<
" in " << regOp.getRegName();
492 return signalPassFailure();
497 Attribute valAttr = regOp.getValue();
498 if (
auto traceEventAttr = dyn_cast<TraceEventAttr>(valAttr)) {
499 if (
auto enumVal = traceEventAttr.getEnumValue()) {
500 value =
static_cast<uint32_t
>(*enumVal);
501 valAttr = builder.getI32IntegerAttr(value);
503 std::string eventName = traceEventAttr.getEventName();
504 std::optional<uint32_t> eventNum =
505 targetModel.lookupEvent(eventName, tileID, isMem);
507 regOp.emitError(
"unknown trace event '") << eventName <<
"'";
508 return signalPassFailure();
511 valAttr = builder.getI32IntegerAttr(value);
514 if (
auto intAttr = dyn_cast<IntegerAttr>(valAttr)) {
516 value = intAttr.getInt();
517 }
else if (
auto strAttr = dyn_cast<StringAttr>(valAttr)) {
519 StringRef valueStr = strAttr.getValue();
524 bool isMasterSlaveField =
525 fieldInfo->
name.find(
"Master_Slave") != std::string::npos;
527 if (!isMasterSlaveField && valueStr.contains(
':')) {
535 StringRef fieldName(fieldInfo->
name);
536 StringRef portSlotPrefix;
537 if (fieldName.starts_with(
"Port_")) {
538 size_t idSuffixPos = fieldName.find(
"_ID");
539 if (idSuffixPos != std::string::npos)
540 portSlotPrefix = fieldName.take_front(idSuffixPos);
544 for (
auto &siblingOp : configOp.getBody().front()) {
545 if (
auto siblingReg = dyn_cast<TraceRegOp>(siblingOp)) {
546 if (siblingReg.getRegName() != regOp.getRegName() ||
547 !siblingReg.getField())
549 StringRef siblingFieldName = *siblingReg.getField();
552 if (!portSlotPrefix.empty()) {
553 if (!siblingFieldName.starts_with(portSlotPrefix) ||
554 !siblingFieldName.contains(
"Master_Slave"))
558 if (!siblingFieldName.contains(
"Master_Slave"))
562 if (
auto siblingInt =
563 dyn_cast<IntegerAttr>(siblingReg.getValue())) {
564 master = (siblingInt.getInt() != 0);
572 targetModel.resolvePortValue(valueStr, tileID, master);
574 regOp.emitError(
"Failed to resolve port value: ") << valueStr;
575 return signalPassFailure();
579 regOp.emitError(
"Unsupported string value: ") << valueStr;
580 return signalPassFailure();
583 regOp.emitError(
"Unsupported value type in pack pass");
584 return signalPassFailure();
588 auto mask = targetModel.getFieldMask(*fieldInfo);
590 regOp.emitError(
"Invalid field bit range for register write: ")
591 << regOp.getRegName() <<
"." << fieldInfo->
name <<
" ["
593 <<
"], width=" << fieldInfo->
getWidth();
594 return signalPassFailure();
596 uint32_t shiftedValue = targetModel.encodeFieldValue(*fieldInfo, value);
598 builder.setInsertionPoint(regOp);
599 builder.create<TraceRegOp>(regOp.getLoc(), regOp.getRegNameAttr(),
601 builder.getI32IntegerAttr(shiftedValue),
602 builder.getI32IntegerAttr(*mask),
603 regOp.getCommentAttr());
615 SmallVector<TraceRegOp> regWrites;
616 for (TraceRegOp op : configOp.getBody().front().getOps<TraceRegOp>()) {
618 regWrites.push_back(op);
623 for (
size_t i = 0; i < regWrites.size() && !changed; ++i) {
624 for (
size_t j = i + 1; j < regWrites.size() && !changed; ++j) {
625 TraceRegOp reg1 = regWrites[i];
626 TraceRegOp reg2 = regWrites[j];
629 if (reg1.getRegName() != reg2.getRegName())
632 auto mask1Attr = reg1.getMask();
633 auto mask2Attr = reg2.getMask();
634 if (!mask1Attr || !mask2Attr)
637 uint32_t mask1 = *mask1Attr;
638 uint32_t mask2 = *mask2Attr;
642 reg1.emitError(
"Overlapping masks for register ")
643 << reg1.getRegName() <<
": mask1=" << mask1
644 <<
" mask2=" << mask2;
645 return signalPassFailure();
649 auto value1Attr = dyn_cast<IntegerAttr>(reg1.getValue());
650 auto value2Attr = dyn_cast<IntegerAttr>(reg2.getValue());
651 if (!value1Attr || !value2Attr) {
653 "Expected integer values for packed register writes");
654 return signalPassFailure();
656 uint32_t value1 = value1Attr.getInt();
657 uint32_t value2 = value2Attr.getInt();
658 uint32_t mergedValue = value1 | value2;
659 uint32_t mergedMask = mask1 | mask2;
662 builder.setInsertionPoint(reg1);
664 if (reg1.getComment())
665 comment += reg1.getComment()->str();
666 if (reg2.getComment()) {
667 if (!comment.empty())
669 comment += reg2.getComment()->str();
672 builder.create<TraceRegOp>(
673 reg1.getLoc(), reg1.getRegNameAttr(),
nullptr,
674 builder.getI32IntegerAttr(mergedValue),
675 builder.getI32IntegerAttr(mergedMask),
676 comment.empty() ? nullptr : builder.getStringAttr(comment));
691std::unique_ptr<OperationPass<DeviceOp>>
693 return std::make_unique<AIETraceRegPackWritesPass>();
std::shared_ptr< Value > value()
Include the generated interface declarations.
std::unique_ptr< mlir::OperationPass< DeviceOp > > createAIETraceRegPackWritesPass()
TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")" TileID
std::unique_ptr< mlir::OperationPass< DeviceOp > > createAIETraceToConfigPass()
Bit field information for a register.
uint32_t getWidth() const
const BitFieldInfo * getField(llvm::StringRef fieldName) const