Skip to content

Commit 696ba5a

Browse files
authored
Enable dynamic lock acquisition for ObjectFIFO acquire/release in cores (#3308)
1 parent f38d918 commit 696ba5a

315 files changed

Lines changed: 10671 additions & 6830 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,34 +1378,49 @@ def AIE_UseLockOp: AIE_Op<"use_lock", []> {
13781378
Then, the value of the lock is decremented by `value`.
13791379
- Release: In AIE1, set the lock to `value`.
13801380
In AIE2, increment the lock by `value`.
1381+
1382+
The lock value is always given as an `i32` SSA `value` operand. Passes that
1383+
need a compile-time constant obtain it via `getConstantValue()`, which
1384+
expects the operand to be defined by an `arith.constant` and fails
1385+
otherwise.
13811386
}];
13821387

13831388
let arguments = (
13841389
ins Index:$lock,
13851390
LockAction:$action,
1386-
OptionalAttr<AIEI32Attr>:$value,
1391+
I32:$value,
13871392
OptionalAttr<LockBlocking>:$blocking,
13881393
DefaultValuedOptionalAttr<BoolAttr, "true">:$acq_en
13891394
);
13901395

13911396
let assemblyFormat = [{
1392-
`(` $lock `,` $action (`,` $value^)? (`,` $blocking^)? `)` attr-dict
1397+
`(` $lock `,` $action `,` $value (`,` $blocking^)? `)` attr-dict
13931398
}];
13941399

13951400
let hasVerifier = 1;
13961401
let builders = [
13971402
OpBuilder<(ins "mlir::Value":$lock,
13981403
"xilinx::AIE::LockAction":$action,
13991404
"int32_t":$value), [{
1400-
build($_builder, $_state, lock, action, $_builder.getI32IntegerAttr(value), nullptr);
1405+
auto constant = mlir::arith::ConstantOp::create(
1406+
$_builder, $_state.location, $_builder.getI32Type(),
1407+
$_builder.getI32IntegerAttr(value));
1408+
build($_builder, $_state, lock, action, constant, /*blocking=*/nullptr);
1409+
}]>,
1410+
OpBuilder<(ins "mlir::Value":$lock,
1411+
"xilinx::AIE::LockAction":$action,
1412+
"mlir::Value":$value), [{
1413+
build($_builder, $_state, lock, action, value, /*blocking=*/nullptr);
14011414
}]>
14021415
];
14031416

14041417
let extraClassDeclaration = [{
14051418
bool acquire() { return (getAction() == LockAction::Acquire); }
14061419
bool acquireGE() { return (getAction() == LockAction::AcquireGreaterEqual); }
14071420
bool release() { return (getAction() == LockAction::Release); }
1408-
int getLockValue() { return getValue().value_or(1); }
1421+
// Returns the compile-time constant lock value when `value` is defined by
1422+
// an arith.constant; otherwise emits an op error and returns failure.
1423+
mlir::FailureOr<int32_t> getConstantValue();
14091424
int getTimeout() {
14101425
// LockBlocking is an EnumAttr.
14111426
if (auto val = getBlocking())

lib/Dialect/AIE/IR/AIEDialect.cpp

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88

99
#include "aie/Dialect/AIE/IR/AIEDialect.h"
1010

11+
#include "mlir/Dialect/Arith/IR/Arith.h"
1112
#include "mlir/Dialect/Func/IR/FuncOps.h"
1213
#include "mlir/Dialect/MemRef/IR/MemRef.h"
1314
#include "mlir/IR/DialectImplementation.h"
15+
#include "mlir/IR/Matchers.h"
1416
#include "mlir/IR/OpDefinition.h"
1517
#include "mlir/IR/SymbolTable.h"
1618
#include "mlir/Interfaces/FoldInterfaces.h"
@@ -73,7 +75,11 @@ struct AIEDialectFoldInterface : DialectFoldInterface {
7375
// them with a core's identical constants, which would leave the core
7476
// referencing a device-level value that is erased when the core is
7577
// outlined.
76-
return isa<CoreOp, RuntimeSequenceOp>(region->getParentOp());
78+
// - Make sure SSA values for aie.use_lock operands in
79+
// aie.mem/aie.memtile_dma/aie.shim_dma bodies do not get
80+
// hoisted.
81+
return isa<CoreOp, RuntimeSequenceOp, MemOp, MemTileDMAOp, ShimDMAOp>(
82+
region->getParentOp());
7783
}
7884
};
7985

@@ -2679,6 +2685,15 @@ LogicalResult LockOp::verify() {
26792685
return success();
26802686
}
26812687

2688+
// Look up for compile-time constant lock values, if any.
2689+
// Returns std::nullopt if lock value does not reference an `arith.constant`.
2690+
static std::optional<int32_t> getConstantLockValue(UseLockOp op) {
2691+
if (auto constant = op.getValue().getDefiningOp<arith::ConstantOp>())
2692+
if (auto intAttr = llvm::dyn_cast<IntegerAttr>(constant.getValue()))
2693+
return (int32_t)intAttr.getInt();
2694+
return std::nullopt;
2695+
}
2696+
26822697
struct UsesOneLockInDMABlock {
26832698
static LogicalResult verifyTrait(Operation *op) {
26842699
auto *block = op->getBlock();
@@ -2700,16 +2715,21 @@ struct AcquireReleaseOneStateInDMABlock {
27002715
auto *block = op->getBlock();
27012716
int acqValue = -1, relValue = -1;
27022717
for (auto op : block->getOps<UseLockOp>()) {
2718+
// Non-constant lock values cannot be compared here; the passes that
2719+
// require a constant enforce that separately via getConstantValue().
2720+
auto value = getConstantLockValue(op);
2721+
if (!value)
2722+
continue;
27032723
if (op.acquire() || op.acquireGE()) {
2704-
if (acqValue != -1 && acqValue != op.getLockValue()) {
2724+
if (acqValue != -1 && acqValue != *value) {
27052725
return failure();
27062726
}
2707-
acqValue = op.getLockValue();
2727+
acqValue = *value;
27082728
} else if (op.release()) {
2709-
if (relValue != -1 && relValue != op.getLockValue()) {
2729+
if (relValue != -1 && relValue != *value) {
27102730
return failure();
27112731
}
2712-
relValue = op.getLockValue();
2732+
relValue = *value;
27132733
}
27142734
}
27152735
return success();
@@ -2737,6 +2757,15 @@ LogicalResult UseLockOp::verify() {
27372757
return (*this)->emitOpError(
27382758
"AcquireGreaterEqual is not supported in AIE1.");
27392759

2760+
// Locks used inside a DMA/BD block are configured via static register writes
2761+
// and therefore require a compile-time constant value.
2762+
if (HasSomeParent<MemOp, MemTileDMAOp, ShimDMAOp>::verifyTrait(*this)
2763+
.succeeded() &&
2764+
!getConstantLockValue(*this))
2765+
return (*this)->emitOpError(
2766+
"lock value in a DMA/BD block must be a compile-time constant "
2767+
"(defined by an arith.constant).");
2768+
27402769
// Otherwise, AIE.useLock should be inside MemOp, MemTileDMAOp, or
27412770
// ShimDMAOp,
27422771
if (HasSomeParent<MemOp, MemTileDMAOp, ShimDMAOp>::verifyTrait(*this)
@@ -2821,9 +2850,17 @@ static void printTraceRegValue(OpAsmPrinter &printer, Operation *op,
28212850
xilinx::AIE::printTraceEventEnum(printer, value);
28222851
}
28232852

2853+
// Helper to parse a LockBlocking enum keyword.
28242854
#define GET_OP_CLASSES
28252855
#include "aie/Dialect/AIE/IR/AIEOps.cpp.inc"
28262856

2857+
FailureOr<int32_t> UseLockOp::getConstantValue() {
2858+
if (auto value = getConstantLockValue(*this))
2859+
return *value;
2860+
return emitOpError("expected the lock value to be a compile-time constant "
2861+
"(defined by an arith.constant).");
2862+
}
2863+
28272864
TileOp SwitchboxOp::getTileOp() {
28282865
return cast<TileElement>(this->getOperation()).getTileOp();
28292866
}

lib/Dialect/AIE/IR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_mlir_dialect_library(AIE
2121

2222
LINK_LIBS PUBLIC
2323
MLIRAIEUtil
24+
MLIRArithDialect
2425
MLIRIR
2526
MLIRSupport
2627
)

lib/Dialect/AIE/Transforms/AIECoreToStandard.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -443,19 +443,19 @@ struct AIEUseLockToStdLowering : OpConversionPattern<UseLockOp> {
443443
return useLock.emitOpError("Could not find the intrinsic function!");
444444

445445
SmallVector<Value, 2> args;
446-
auto lockValue = useLock.getLockValue();
446+
auto i32Ty = IntegerType::get(rewriter.getContext(), 32);
447+
args.push_back(arith::IndexCastOp::create(rewriter, useLock.getLoc(),
448+
i32Ty, useLock.getLock()));
447449

448-
// AIE2 acquire greater equal is encoded as a negative value.
450+
Value value = adaptor.getValue();
451+
// AIE2 acquire-greater-equal is encoded as a negative value, so negate
452+
// it at runtime.
449453
if (useLock.acquireGE()) {
450-
lockValue = -lockValue;
454+
Value zero = arith::ConstantOp::create(
455+
rewriter, useLock.getLoc(), i32Ty, rewriter.getI32IntegerAttr(0));
456+
value = arith::SubIOp::create(rewriter, useLock.getLoc(), zero, value);
451457
}
452-
args.push_back(arith::IndexCastOp::create(
453-
rewriter, useLock.getLoc(),
454-
IntegerType::get(rewriter.getContext(), 32), useLock.getLock()));
455-
args.push_back(
456-
arith::ConstantOp::create(rewriter, useLock.getLoc(),
457-
IntegerType::get(rewriter.getContext(), 32),
458-
rewriter.getI32IntegerAttr(lockValue)));
458+
args.push_back(value);
459459

460460
func::CallOp::create(rewriter, useLock.getLoc(), useLockFunc, args);
461461
}

0 commit comments

Comments
 (0)