CIRCT  19.0.0git
Classes | Namespaces | Macros | Functions
PrepareForEmission.cpp File Reference
#include "ExportVerilogInternals.h"
#include "circt/Conversion/ExportVerilog.h"
#include "circt/Dialect/Comb/CombOps.h"
#include "circt/Dialect/Debug/DebugDialect.h"
#include "circt/Dialect/LTL/LTLDialect.h"
#include "circt/Dialect/Verif/VerifDialect.h"
#include "circt/Support/LoweringOptions.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "mlir/Pass/Pass.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/TypeSwitch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "circt/Conversion/Passes.h.inc"
Include dependency graph for PrepareForEmission.cpp:

Go to the source code of this file.

Classes

struct  EmittedExpressionState
 
class  EmittedExpressionStateManager
 This class handles information about AST structures of each expressions. More...
 
struct  WireLowering
 

Namespaces

 circt
 The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
 

Macros

#define DEBUG_TYPE   "prepare-for-emission"
 
#define GEN_PASS_DEF_PREPAREFOREMISSION
 

Functions

static bool shouldSpillWire (Operation &op, const LoweringOptions &options)
 
static StringAttr getArgName (Operation *op, size_t idx)
 
static void spillWiresForInstanceInputs (HWInstanceLike op)
 
static void replacePortWithWire (ImplicitLocOpBuilder &builder, Operation *op, Value result, StringRef name)
 
static StringAttr getResName (Operation *op, size_t idx)
 
static void lowerInstanceResults (HWInstanceLike op)
 
static void lowerFunctionCallResults (Operation *op)
 
static void lowerUsersToTemporaryWire (Operation &op, bool emitWireAtBlockBegin=false)
 Emit an explicit wire or logic to assign operation's result. More...
 
static void lowerAlwaysInlineOperation (Operation *op, const LoweringOptions &options)
 
static std::pair< Block *, Block::iterator > findLogicOpInsertionPoint (Operation *op)
 
static Value lowerFullyAssociativeOp (Operation &op, OperandRange operands, SmallVector< Operation * > &newOps)
 Lower a variadic fully-associative operation into an expression tree. More...
 
static Operation * rewriteAddWithNegativeConstant (comb::AddOp add, hw::ConstantOp rhsCst)
 Transform "a + -cst" ==> "a - cst" for prettier output. More...
 
static Operation * lowerStructExplodeOp (hw::StructExplodeOp op)
 
static Operation * findParentInNonProceduralRegion (Operation *op)
 Given an operation in a procedural region, scan up the region tree to find the first operation in a graph region (typically an always or initial op). More...
 
static bool rewriteSideEffectingExpr (Operation *op)
 This function is invoked on side effecting Verilog expressions when we're in 'disallowLocalVariables' mode for old Verilog clients. More...
 
static bool hoistNonSideEffectExpr (Operation *op)
 This function is called for non-side-effecting Verilog expressions when we're in 'disallowLocalVariables' mode for old Verilog clients. More...
 
static bool isMovableDeclaration (Operation *op)
 Check whether an op is a declaration that can be moved. More...
 
static bool reuseExistingInOut (Operation *op, const LoweringOptions &options)
 If exactly one use of this op is an assign, replace the other uses with a read from the assigned wire or reg. More...
 
static void prettifyAfterLegalization (Block &block, EmittedExpressionStateManager &expressionStateManager)
 After the legalization, we are able to know accurate verilog AST structures. More...
 
static void buildWireLowerings (Block &block, SmallVectorImpl< WireLowering > &wireLowerings)
 Determine the insertion location of declaration and assignment ops for hw::WireOps in a block. More...
 
static void applyWireLowerings (Block &block, ArrayRef< WireLowering > wireLowerings)
 Materialize the SV wire declaration and assignment operations in the locations previously determined by a call to buildWireLowerings. More...
 
static LogicalResult legalizeHWModule (Block &block, const LoweringOptions &options)
 For each module we emit, do a prepass over the structure, pre-lowering and otherwise rewriting operations we don't want to emit. More...
 

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "prepare-for-emission"

Definition at line 36 of file PrepareForEmission.cpp.

◆ GEN_PASS_DEF_PREPAREFOREMISSION

#define GEN_PASS_DEF_PREPAREFOREMISSION

Definition at line 39 of file PrepareForEmission.cpp.

Function Documentation

◆ applyWireLowerings()

static void applyWireLowerings ( Block &  block,
ArrayRef< WireLowering wireLowerings 
)
static

Materialize the SV wire declaration and assignment operations in the locations previously determined by a call to buildWireLowerings.

This replaces all hw::WireOps with their appropriate SV counterpart.

Definition at line 850 of file PrepareForEmission.cpp.

References sv.WireOp::create(), and sv.AssignOp::create().

Referenced by legalizeHWModule().

◆ buildWireLowerings()

static void buildWireLowerings ( Block &  block,
SmallVectorImpl< WireLowering > &  wireLowerings 
)
static

Determine the insertion location of declaration and assignment ops for hw::WireOps in a block.

This function tries to place the declaration point as late as possible, right before the very first use of the wire. It also tries to place the assign point as early as possible, right after the assigned value becomes available.

Definition at line 821 of file PrepareForEmission.cpp.

Referenced by legalizeHWModule().

◆ findLogicOpInsertionPoint()

static std::pair<Block *, Block::iterator> findLogicOpInsertionPoint ( Operation *  op)
static

Definition at line 380 of file PrepareForEmission.cpp.

Referenced by legalizeHWModule().

◆ findParentInNonProceduralRegion()

static Operation* findParentInNonProceduralRegion ( Operation *  op)
static

Given an operation in a procedural region, scan up the region tree to find the first operation in a graph region (typically an always or initial op).

By looking for a graph region, we will stop at graph-region #ifdef's that may enclose this operation.

Definition at line 467 of file PrepareForEmission.cpp.

References assert().

Referenced by hoistNonSideEffectExpr(), legalizeHWModule(), and rewriteSideEffectingExpr().

◆ getArgName()

static StringAttr getArgName ( Operation *  op,
size_t  idx 
)
static

Definition at line 76 of file PrepareForEmission.cpp.

Referenced by spillWiresForInstanceInputs().

◆ getResName()

static StringAttr getResName ( Operation *  op,
size_t  idx 
)
static

Definition at line 145 of file PrepareForEmission.cpp.

Referenced by lowerInstanceResults().

◆ hoistNonSideEffectExpr()

static bool hoistNonSideEffectExpr ( Operation *  op)
static

This function is called for non-side-effecting Verilog expressions when we're in 'disallowLocalVariables' mode for old Verilog clients.

It hoists non-constant expressions out to the top level so they don't turn into local variable declarations.

Definition at line 517 of file PrepareForEmission.cpp.

References findParentInNonProceduralRegion(), and circt::ExportVerilog::isExpressionAlwaysInline().

Referenced by legalizeHWModule().

◆ isMovableDeclaration()

static bool isMovableDeclaration ( Operation *  op)
static

Check whether an op is a declaration that can be moved.

Definition at line 570 of file PrepareForEmission.cpp.

Referenced by legalizeHWModule().

◆ legalizeHWModule()

static LogicalResult legalizeHWModule ( Block &  block,
const LoweringOptions options 
)
static

◆ lowerAlwaysInlineOperation()

static void lowerAlwaysInlineOperation ( Operation *  op,
const LoweringOptions options 
)
static

◆ lowerFullyAssociativeOp()

static Value lowerFullyAssociativeOp ( Operation &  op,
OperandRange  operands,
SmallVector< Operation * > &  newOps 
)
static

Lower a variadic fully-associative operation into an expression tree.

This enables long-line splitting to work with them. NOLINTNEXTLINE(misc-no-recursion)

Definition at line 390 of file PrepareForEmission.cpp.

References assert().

Referenced by legalizeHWModule().

◆ lowerFunctionCallResults()

static void lowerFunctionCallResults ( Operation *  op)
static

Definition at line 202 of file PrepareForEmission.cpp.

References assert(), getBodyBlock(), and replacePortWithWire().

Referenced by legalizeHWModule().

◆ lowerInstanceResults()

static void lowerInstanceResults ( HWInstanceLike  op)
static

◆ lowerStructExplodeOp()

static Operation* lowerStructExplodeOp ( hw::StructExplodeOp  op)
static

Definition at line 446 of file PrepareForEmission.cpp.

Referenced by legalizeHWModule().

◆ lowerUsersToTemporaryWire()

static void lowerUsersToTemporaryWire ( Operation &  op,
bool  emitWireAtBlockBegin = false 
)
static

Emit an explicit wire or logic to assign operation's result.

This function is used to create a temporary to legalize a verilog expression or to resolve use-before-def in a graph region. If emitWireAtBlockBegin is true, a temporary wire will be created at the beginning of the block. Otherwise, a wire is created just after op's position so that we can inline the assignment into its wire declaration.

Definition at line 234 of file PrepareForEmission.cpp.

References Python.support::connect(), sv.WireOp::create(), sv.ReadInOutOp::create(), and circt::ExportVerilog::inferStructuralNameForTemporary().

Referenced by legalizeHWModule(), lowerAlwaysInlineOperation(), and prettifyAfterLegalization().

◆ prettifyAfterLegalization()

static void prettifyAfterLegalization ( Block &  block,
EmittedExpressionStateManager expressionStateManager 
)
static

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.

Definition at line 786 of file PrepareForEmission.cpp.

References circt::ExportVerilog::isVerilogExpression(), lowerUsersToTemporaryWire(), and EmittedExpressionStateManager::shouldSpillWireBasedOnState().

Referenced by circt::ExportVerilog::prepareHWModule().

◆ replacePortWithWire()

static void replacePortWithWire ( ImplicitLocOpBuilder &  builder,
Operation *  op,
Value  result,
StringRef  name 
)
static

Definition at line 116 of file PrepareForEmission.cpp.

References Python.support::connect(), and sv.WireOp::create().

Referenced by lowerFunctionCallResults().

◆ reuseExistingInOut()

static bool reuseExistingInOut ( Operation *  op,
const LoweringOptions options 
)
static

If exactly one use of this op is an assign, replace the other uses with a read from the assigned wire or reg.

This assumes the preconditions for doing so are met: op must be an expression in a non-procedural region.

Definition at line 683 of file PrepareForEmission.cpp.

References circt::ExportVerilog::isExpressionAlwaysInline(), and lowerAlwaysInlineOperation().

Referenced by legalizeHWModule().

◆ rewriteAddWithNegativeConstant()

static Operation* rewriteAddWithNegativeConstant ( comb::AddOp  add,
hw::ConstantOp  rhsCst 
)
static

Transform "a + -cst" ==> "a - cst" for prettier output.

This returns the first operation emitted.

Definition at line 429 of file PrepareForEmission.cpp.

References hw.ConstantOp::create().

Referenced by legalizeHWModule().

◆ rewriteSideEffectingExpr()

static bool rewriteSideEffectingExpr ( Operation *  op)
static

This function is invoked on side effecting Verilog expressions when we're in 'disallowLocalVariables' mode for old Verilog clients.

This ensures that any side effecting expressions are only used by a single BPAssign to a sv.reg or sv.logic operation. This ensures that the verilog emitter doesn't have to worry about spilling them.

This returns true if the op was rewritten, false otherwise.

Definition at line 483 of file PrepareForEmission.cpp.

References assert(), sv.ReadInOutOp::create(), findParentInNonProceduralRegion(), and seq::reg().

Referenced by legalizeHWModule().

◆ shouldSpillWire()

static bool shouldSpillWire ( Operation &  op,
const LoweringOptions options 
)
static

◆ spillWiresForInstanceInputs()

static void spillWiresForInstanceInputs ( HWInstanceLike  op)
static