@@ -2304,8 +2304,7 @@ class ExprEmitter : public EmitterBase,
23042304
23052305 // / Emit braced list of values surrounded by `{` and `}`.
23062306 void emitBracedList (ValueRange ops) {
2307- return emitBracedList (
2308- ops, [&]() { ps << " {" ; }, [&]() { ps << " }" ; });
2307+ return emitBracedList (ops, [&]() { ps << " {" ; }, [&]() { ps << " }" ; });
23092308 }
23102309
23112310 // / Print an APInt constant.
@@ -3603,6 +3602,12 @@ class PropertyEmitter : public EmitterBase,
36033602 // / location information tracking.
36043603 SmallPtrSetImpl<Operation *> &emittedOps;
36053604
3605+ // / Current clock context from enclosing ltl.clock op. Used to verify that
3606+ // / ltl.delay ops have consistent clocks, since SVA does not support
3607+ // / per-delay clocks.
3608+ Value currentClock;
3609+ std::optional<ltl::ClockEdge> currentEdge;
3610+
36063611 // / Tokens buffered for inserting casts/parens after emitting children.
36073612 SmallVector<Token> localTokens;
36083613
@@ -3752,6 +3757,26 @@ EmittedProperty PropertyEmitter::visitLTL(ltl::IntersectOp op) {
37523757}
37533758
37543759EmittedProperty PropertyEmitter::visitLTL (ltl::DelayOp op) {
3760+ // Verify that the delay's clock matches the enclosing clock context.
3761+ // SVA does not support per-delay clocks; all delays inherit from the
3762+ // enclosing @(edge clock) specification.
3763+ Value delayClock = op.getClock ();
3764+ if (currentClock) {
3765+ // Check if delay has a real clock (not a placeholder constant)
3766+ bool isPlaceholder = false ;
3767+ if (auto constOp = delayClock.getDefiningOp <hw::ConstantOp>()) {
3768+ auto value = constOp.getValue ();
3769+ isPlaceholder = value.getBitWidth () == 1 && value.isOne ();
3770+ }
3771+
3772+ if (!isPlaceholder && delayClock != currentClock) {
3773+ emitOpError (op, " delay clock does not match enclosing clock; "
3774+ " SVA does not support per-delay clocks" );
3775+ } else if (!isPlaceholder && currentEdge && op.getEdge () != *currentEdge) {
3776+ emitOpError (op, " delay clock edge does not match enclosing clock edge" );
3777+ }
3778+ }
3779+
37553780 ps << " ##" ;
37563781 if (auto length = op.getLength ()) {
37573782 if (*length == 0 ) {
@@ -3907,7 +3932,18 @@ EmittedProperty PropertyEmitter::visitLTL(ltl::ClockOp op) {
39073932 ps << " )" ;
39083933 });
39093934 ps << PP::space;
3935+
3936+ // Set the clock context for nested property emission.
3937+ // Save and restore to handle nested clock ops correctly.
3938+ Value savedClock = currentClock;
3939+ auto savedEdge = currentEdge;
3940+ currentClock = op.getClock ();
3941+ currentEdge = op.getEdge ();
3942+
39103943 emitNestedProperty (op.getInput (), PropertyPrecedence::Clocking);
3944+
3945+ currentClock = savedClock;
3946+ currentEdge = savedEdge;
39113947 return {PropertyPrecedence::Clocking};
39123948}
39133949
0 commit comments