@@ -468,89 +468,98 @@ addFragments(hw::HWModuleOp module,
468468static bool moveOpsIntoIfdefGuardsAndProcesses (Operation *rootOp) {
469469 bool usedSynthesisMacro = false ;
470470
471- rootOp->walk ([&](Operation *op) {
472- auto loc = op->getLoc ();
473-
474- // Move the op into an ifdef guard if needed.
475- if (needsIfdefGuard (op)) {
476- // Try to reuse an ifdef guard immediately before the op.
477- Block *block = nullptr ;
478- if (op->getPrevNode ())
479- block = TypeSwitch<Operation *, Block *>(op->getPrevNode ())
480- .Case <sv::IfDefOp, sv::IfDefProceduralOp>(
481- [&](auto guardOp) -> Block * {
482- if (guardOp.getCond ().getIdent ().getAttr () ==
483- " SYNTHESIS" &&
484- guardOp.hasElse ())
485- return guardOp.getElseBlock ();
486- return nullptr ;
487- })
488- .Default ([](auto ) { return nullptr ; });
489-
490- // If there was no pre-existing guard, create one.
491- if (!block) {
492- OpBuilder builder (op);
493- if (op->getParentOp ()->hasTrait <ProceduralRegion>())
494- block = sv::IfDefProceduralOp::create (
495- builder, loc, " SYNTHESIS" , [] {}, [] {})
496- .getElseBlock ();
497- else
498- block = sv::IfDefOp::create (
499- builder, loc, " SYNTHESIS" , [] {}, [] {})
500- .getElseBlock ();
501- usedSynthesisMacro = true ;
502- }
471+ rootOp->walk <mlir::WalkOrder::PreOrder>(
472+ [&](Operation *op) -> mlir::WalkResult {
473+ // `sim.triggered` is lowered as a whole later on. Do not pre-wrap the
474+ // ops nested inside it here, or we may create redundant/invalid
475+ // structure.
476+ if (isa<TriggeredOp>(op))
477+ return mlir::WalkResult::skip ();
478+
479+ auto loc = op->getLoc ();
480+
481+ // Move the op into an ifdef guard if needed.
482+ if (needsIfdefGuard (op)) {
483+ // Try to reuse an ifdef guard immediately before the op.
484+ Block *block = nullptr ;
485+ if (op->getPrevNode ())
486+ block = TypeSwitch<Operation *, Block *>(op->getPrevNode ())
487+ .Case <sv::IfDefOp, sv::IfDefProceduralOp>(
488+ [&](auto guardOp) -> Block * {
489+ if (guardOp.getCond ().getIdent ().getAttr () ==
490+ " SYNTHESIS" &&
491+ guardOp.hasElse ())
492+ return guardOp.getElseBlock ();
493+ return nullptr ;
494+ })
495+ .Default ([](auto ) { return nullptr ; });
496+
497+ // If there was no pre-existing guard, create one.
498+ if (!block) {
499+ OpBuilder builder (op);
500+ if (op->getParentOp ()->hasTrait <ProceduralRegion>())
501+ block = sv::IfDefProceduralOp::create (
502+ builder, loc, " SYNTHESIS" , [] {}, [] {})
503+ .getElseBlock ();
504+ else
505+ block = sv::IfDefOp::create (
506+ builder, loc, " SYNTHESIS" , [] {}, [] {})
507+ .getElseBlock ();
508+ usedSynthesisMacro = true ;
509+ }
503510
504- // Move the op into the guard block.
505- op->moveBefore (block, block->end ());
506- }
511+ // Move the op into the guard block.
512+ op->moveBefore (block, block->end ());
513+ }
507514
508- // Check if the op requires an clock and condition wrapper.
509- auto [clock, condition] = needsClockAndConditionWrapper (op);
510-
511- // Create an enclosing always process.
512- if (clock) {
513- // Try to reuse an always process immediately before the op.
514- Block *block = nullptr ;
515- if (auto alwaysOp = dyn_cast_or_null<sv::AlwaysOp>(op->getPrevNode ()))
516- if (alwaysOp.getNumConditions () == 1 &&
517- alwaysOp.getCondition (0 ).event == sv::EventControl::AtPosEdge)
518- if (auto clockOp = alwaysOp.getCondition (0 )
519- .value .getDefiningOp <seq::FromClockOp>())
520- if (clockOp.getInput () == clock)
521- block = alwaysOp.getBodyBlock ();
522-
523- // If there was no pre-existing always process, create one.
524- if (!block) {
525- OpBuilder builder (op);
526- clock = seq::FromClockOp::create (builder, loc, clock);
527- block = sv::AlwaysOp::create (builder, loc, sv::EventControl::AtPosEdge,
528- clock, [] {})
529- .getBodyBlock ();
530- }
515+ // Check if the op requires an clock and condition wrapper.
516+ auto [clock, condition] = needsClockAndConditionWrapper (op);
517+
518+ // Create an enclosing always process.
519+ if (clock) {
520+ // Try to reuse an always process immediately before the op.
521+ Block *block = nullptr ;
522+ if (auto alwaysOp = dyn_cast_or_null<sv::AlwaysOp>(op->getPrevNode ()))
523+ if (alwaysOp.getNumConditions () == 1 &&
524+ alwaysOp.getCondition (0 ).event == sv::EventControl::AtPosEdge)
525+ if (auto clockOp = alwaysOp.getCondition (0 )
526+ .value .getDefiningOp <seq::FromClockOp>())
527+ if (clockOp.getInput () == clock)
528+ block = alwaysOp.getBodyBlock ();
529+
530+ // If there was no pre-existing always process, create one.
531+ if (!block) {
532+ OpBuilder builder (op);
533+ clock = seq::FromClockOp::create (builder, loc, clock);
534+ block = sv::AlwaysOp::create (
535+ builder, loc, sv::EventControl::AtPosEdge, clock, [] {})
536+ .getBodyBlock ();
537+ }
531538
532- // Move the op into the process.
533- op->moveBefore (block, block->end ());
534- }
539+ // Move the op into the process.
540+ op->moveBefore (block, block->end ());
541+ }
535542
536- // Create an enclosing if condition.
537- if (condition) {
538- // Try to reuse an if statement immediately before the op.
539- Block *block = nullptr ;
540- if (auto ifOp = dyn_cast_or_null<sv::IfOp>(op->getPrevNode ()))
541- if (ifOp.getCond () == condition)
542- block = ifOp.getThenBlock ();
543-
544- // If there was no pre-existing if statement, create one.
545- if (!block) {
546- OpBuilder builder (op);
547- block = sv::IfOp::create (builder, loc, condition, [] {}).getThenBlock ();
548- }
543+ // Create an enclosing if condition.
544+ if (condition) {
545+ // Try to reuse an if statement immediately before the op.
546+ Block *block = nullptr ;
547+ if (auto ifOp = dyn_cast_or_null<sv::IfOp>(op->getPrevNode ()))
548+ if (ifOp.getCond () == condition)
549+ block = ifOp.getThenBlock ();
550+
551+ // If there was no pre-existing if statement, create one.
552+ if (!block) {
553+ OpBuilder builder (op);
554+ block =
555+ sv::IfOp::create (builder, loc, condition, [] {}).getThenBlock ();
556+ }
549557
550- // Move the op into the if body.
551- op->moveBefore (block, block->end ());
552- }
553- });
558+ // Move the op into the if body.
559+ op->moveBefore (block, block->end ());
560+ }
561+ return mlir::WalkResult::advance ();
562+ });
554563
555564 return usedSynthesisMacro;
556565}
0 commit comments