diff --git a/lib/Conversion/ExportVerilog/PrepareForEmission.cpp b/lib/Conversion/ExportVerilog/PrepareForEmission.cpp index 184b6c67927b..57ac1b15a1c7 100644 --- a/lib/Conversion/ExportVerilog/PrepareForEmission.cpp +++ b/lib/Conversion/ExportVerilog/PrepareForEmission.cpp @@ -779,8 +779,11 @@ bool EmittedExpressionStateManager::shouldSpillWireBasedOnState(Operation &op) { /// After the legalization, we are able to know accurate verilog AST structures. /// So this function walks and prettifies verilog IR with a heuristic method /// specified by `options.wireSpillingHeuristic` based on the structures. +/// Also move the declarations to the top of the block when +/// `disallowDeclAssignments` is set. static void prettifyAfterLegalization( - Block &block, EmittedExpressionStateManager &expressionStateManager) { + Block &block, const LoweringOptions &options, + EmittedExpressionStateManager &expressionStateManager) { // TODO: Handle procedural regions as well. if (block.getParentOp()->hasTrait()) return; @@ -794,11 +797,20 @@ static void prettifyAfterLegalization( } } - for (auto &op : block) { + // Recursively process nested regions, and move declarations to the top of the + // block when `disallowDeclAssignments` is set. + Operation *insertionPoint = block.empty() ? nullptr : &block.front(); + for (auto &op : llvm::make_early_inc_range(block)) { // If the operations has regions, visit each of the region bodies. for (auto ®ion : op.getRegions()) { if (!region.empty()) - prettifyAfterLegalization(region.front(), expressionStateManager); + prettifyAfterLegalization(region.front(), options, + expressionStateManager); + } + + if (options.disallowDeclAssignments && isMovableDeclaration(&op)) { + op.moveBefore(insertionPoint); + insertionPoint = op.getNextNode(); } } } @@ -1384,7 +1396,8 @@ LogicalResult ExportVerilog::prepareHWModule(hw::HWEmittableModuleLike module, EmittedExpressionStateManager expressionStateManager(options); // Spill wires to prettify verilog outputs. - prettifyAfterLegalization(*module.getBodyBlock(), expressionStateManager); + prettifyAfterLegalization(*module.getBodyBlock(), options, + expressionStateManager); return success(); } diff --git a/test/Conversion/ExportVerilog/decl-assignments.mlir b/test/Conversion/ExportVerilog/decl-assignments.mlir index a0dd59044dd5..0bbdc212c7ff 100644 --- a/test/Conversion/ExportVerilog/decl-assignments.mlir +++ b/test/Conversion/ExportVerilog/decl-assignments.mlir @@ -3,11 +3,16 @@ // CHECK-LABEL: module test( hw.module @test(in %v: i1) { - // ALLOW: wire w = v; - // DISALLOW: wire w; - // DISALLOW: assign w = v; + // ALLOW: wire w = v; + // DISALLOW: wire w; + // DISALLOW-NEXT: wire u; + // DISALLOW-NEXT: wire x; + // DISALLOW-NEXT: assign w = v; + // DISALLOW-NEXT: assign u = v; %w = sv.wire : !hw.inout sv.assign %w, %v : i1 + %u = sv.wire : !hw.inout + sv.assign %u, %v : i1 // CHECK: initial begin sv.initial { // ALLOW: automatic logic l = v; @@ -16,4 +21,8 @@ hw.module @test(in %v: i1) { %l = sv.logic : !hw.inout sv.bpassign %l, %v : i1 } + // ALLOW: wire x = v; + // DISALLOW: assign x = v; + %x = sv.wire : !hw.inout + sv.assign %x, %v : i1 }