@@ -127,13 +127,14 @@ struct AIEDMATasksToNPUPass : AIEDMATasksToNPUBase<AIEDMATasksToNPUPass> {
127127
128128 LogicalResult verifyOptionalLocksInBlock (Block &block) {
129129 auto lock_ops = block.getOps <AIE ::UseLockOp>();
130- // Exactly 0 or 2 lock ops
131130 int n_lock_ops = std::distance (lock_ops.begin (), lock_ops.end ());
132- if (n_lock_ops > 0 ) {
133- // TODO: Not yet implemented
131+ // Allow exactly 0 or 2 lock ops (acquire and release)
132+ if (n_lock_ops != 0 && n_lock_ops != 2 ) {
134133 AIE ::UseLockOp lock_op = *lock_ops.begin ();
135- lock_op.emitOpError (" Lowering for lock operations in NPU runtime "
136- " configuration is not yet implemented." );
134+ lock_op.emitOpError (
135+ " BD blocks must have either 0 or 2 lock operations (acquire and "
136+ " release). Found " )
137+ << n_lock_ops << " lock operations." ;
137138 return failure ();
138139 }
139140 return success ();
@@ -172,10 +173,30 @@ struct AIEDMATasksToNPUPass : AIEDMATasksToNPUBase<AIEDMATasksToNPUPass> {
172173 return bd_op;
173174 }
174175
176+ // Returns pair of (acquire_lock_op, release_lock_op) if present
175177 std::optional<std::pair<AIE ::UseLockOp, AIE ::UseLockOp>>
176178 getOptionalLockOpsForBlock (Block &block) {
177- // auto lock_ops = block.getOps<AIE::UseLockOp>();
178- return std::nullopt ; // Not yet implemented
179+ auto lock_ops = block.getOps <AIE ::UseLockOp>();
180+ int n_lock_ops = std::distance (lock_ops.begin (), lock_ops.end ());
181+ if (n_lock_ops != 2 ) {
182+ return std::nullopt ;
183+ }
184+
185+ AIE ::UseLockOp acquire_op = nullptr ;
186+ AIE ::UseLockOp release_op = nullptr ;
187+
188+ for (auto lock_op : lock_ops) {
189+ if (lock_op.acquire () || lock_op.acquireGE ()) {
190+ acquire_op = lock_op;
191+ } else if (lock_op.release ()) {
192+ release_op = lock_op;
193+ }
194+ }
195+
196+ if (acquire_op && release_op) {
197+ return std::make_pair (acquire_op, release_op);
198+ }
199+ return std::nullopt ;
179200 }
180201
181202 LogicalResult setAddressForSingleBD (OpBuilder &builder, AIE ::DMABDOp &bd_op,
@@ -435,27 +456,69 @@ struct AIEDMATasksToNPUPass : AIEDMATasksToNPUBase<AIEDMATasksToNPUPass> {
435456 packet_id = info.getPktId ();
436457 }
437458
459+ // Extract lock information if present
460+ int32_t lock_rel_val = 0 ;
461+ int32_t lock_rel_id = 0 ;
462+ int32_t lock_acq_enable = 0 ;
463+ int32_t lock_acq_val = 0 ;
464+ int32_t lock_acq_id = 0 ;
465+
466+ auto lock_ops = getOptionalLockOpsForBlock (block);
467+ if (lock_ops) {
468+ auto [acquire_op, release_op] = *lock_ops;
469+
470+ // Get lock IDs from the lock operations
471+ AIE ::LockOp acq_lock = acquire_op.getLockOp ();
472+ AIE ::LockOp rel_lock = release_op.getLockOp ();
473+
474+ if (acq_lock.getLockID ().has_value ()) {
475+ lock_acq_id = acq_lock.getLockID ().value ();
476+ lock_acq_val = acquire_op.getLockValue ();
477+ // For AcquireGreaterEqual, negate the value to signal the hardware
478+ // to use >= comparison instead of == comparison.
479+ if (acquire_op.acquireGE ())
480+ lock_acq_val = -lock_acq_val;
481+ lock_acq_enable = 1 ;
482+ }
483+
484+ if (rel_lock.getLockID ().has_value ()) {
485+ lock_rel_id = rel_lock.getLockID ().value ();
486+ lock_rel_val = release_op.getLockValue ();
487+ }
488+
489+ // For memtile, add lock offset using getLockLocalBaseIndex.
490+ // This matches AIERT.cpp implementation.
491+ if (target_model.isMemTile (tile.getCol (), tile.getRow ())) {
492+ auto lockOffset = target_model.getLockLocalBaseIndex (
493+ tile.getCol (), tile.getRow (), acq_lock.colIndex (),
494+ acq_lock.rowIndex ());
495+ if (lockOffset && acq_lock.getLockID ().has_value ())
496+ lock_acq_id += lockOffset.value ();
497+ if (lockOffset && rel_lock.getLockID ().has_value ())
498+ lock_rel_id += lockOffset.value ();
499+ }
500+ }
501+
438502 NpuWriteBdOp::create (
439503 builder, bd_op.getLoc (), tile.getCol (), bd_id, len_addr_granularity,
440504 offset,
441505 /* enable_packet=*/ enable_packet,
442506 /* out_of_order_id=*/ out_of_order_id,
443507 /* packet_id=*/ packet_id,
444508 /* packet_type=*/ packet_type,
445- /* TODO: Strides/Wraps */
446509 /* d0_size=*/ d0size, /* d0_stride=*/ d0stride,
447510 /* d1_size=*/ d1size, /* d1_stride=*/ d1stride,
448511 /* d2_size=*/ d2size, /* d2_stride=*/ d2stride,
449512 /* iteration_current=*/ 0 , /* iteration_size=*/ iteration_size,
450513 /* iteration_stride=*/ iteration_stride,
451- /* TODO: Next BD */
452514 /* next_bd=*/ next_bd_id,
453515 /* row=*/ tile.getRow (),
454516 /* use_next_bd=*/ use_next_bd,
455517 /* valid_bd=*/ 1 ,
456- /* TODO: Locks */
457- /* lock_rel_val=*/ 0 , /* lock_rel_id=*/ 0 , /* lock_acq_enable=*/ 0 ,
458- /* lock_acq_val=*/ 0 , /* lock_ackq_id=*/ 0 , /* d0_zero_before=*/ padBefore[0 ],
518+ /* lock_rel_val=*/ lock_rel_val, /* lock_rel_id=*/ lock_rel_id,
519+ /* lock_acq_enable=*/ lock_acq_enable,
520+ /* lock_acq_val=*/ lock_acq_val, /* lock_acq_id=*/ lock_acq_id,
521+ /* d0_zero_before=*/ padBefore[0 ],
459522 /* d1_zero_before=*/ padBefore[1 ], /* d2_zero_before=*/ padBefore[2 ],
460523 /* d0_zero_after=*/ padAfter[0 ], /* d1_zero_after=*/ padAfter[1 ],
461524 /* d2_zero_after=*/ padAfter[2 ],
0 commit comments