28#include "mlir/IR/Builders.h"
29#include "mlir/Pass/Pass.h"
30#include "llvm/ADT/TypeSwitch.h"
34#define GEN_PASS_DEF_SVMASKNONSYNTHESIZABLE
35#include "circt/Dialect/SV/SVPasses.h.inc"
48 return isa<sv::AssertConcurrentOp, sv::AssumeConcurrentOp,
49 sv::CoverConcurrentOp, sv::AssertPropertyOp, sv::AssumePropertyOp,
50 sv::CoverPropertyOp>(op);
57 StringRef expectedMacro) {
58 return llvm::TypeSwitch<Operation *, Region *>(op)
59 .Case<
sv::IfDefOp, sv::IfDefProceduralOp>([&](
auto ifdef) -> Region * {
60 if (ifdef.getCond().getName() != expectedMacro)
62 return &ifdef.getElseRegion();
64 .Default(
static_cast<Region *
>(
nullptr));
76 StringRef verilogName,
bool &created) {
77 for (
auto decl : moduleOp.getOps<sv::MacroDeclOp>()) {
78 if (decl.getMacroIdentifier() == verilogName) {
80 return decl.getSymNameAttr();
85 StringRef name = ns.
newName(verilogName);
87 return StringAttr::get(moduleOp.getContext(), name);
92 block.walk([&](Operation *op) {
101 OpBuilder builder(op);
102 Location loc = op->getLoc();
109 sv::IfDefProceduralOp::create(builder, loc, macro,
113 elseBlock = sv::IfDefOp::create(builder, loc, macro, {},
118 op->moveBefore(elseBlock, elseBlock->end());
126 bool changed =
false;
129 for (Operation &op : llvm::make_early_inc_range(block)) {
136 for (Region ®ion : op.getRegions()) {
137 if (®ion == guardedElseRegion)
139 for (Block &nested : region)
151struct SVMaskNonSynthesizablePass
152 :
public circt::sv::impl::SVMaskNonSynthesizableBase<
153 SVMaskNonSynthesizablePass> {
155 void runOnOperation()
override;
159void SVMaskNonSynthesizablePass::runOnOperation() {
160 mlir::ModuleOp moduleOp = getOperation();
164 StringAttr macroSymName;
165 bool macroDeclNeedsCreation =
false;
166 if (mode == MaskNonSynthesizableMode::Ifdef)
169 StringRef passDownMacro =
170 macroSymName ? macroSymName.getValue() : StringRef();
173 SmallVector<hw::HWModuleOp> hwModules(moduleOp.getOps<
hw::HWModuleOp>());
174 unsigned numChanged =
177 Block &body = *hwModule.getBodyBlock();
179 case MaskNonSynthesizableMode::Delete:
182 case MaskNonSynthesizableMode::Ifdef:
185 llvm_unreachable(
"all modes handled");
188 if (mode == MaskNonSynthesizableMode::Ifdef && numChanged > 0 &&
189 macroDeclNeedsCreation) {
190 auto builder = OpBuilder::atBlockBegin(moduleOp.getBody());
191 sv::MacroDeclOp::create(builder, moduleOp.getLoc(), macroSymName,
192 ArrayAttr{}, builder.getStringAttr(macro));
static bool isMaskedOp(Operation *op)
Returns true if op is one of the SV ops we mask.
static void maskOpByIfdef(Operation *op, StringRef macro)
Wrap a single masked op in its own sv.ifdef/sv.ifdef.procedural.
static Region * getMatchingIfDefElseRegion(Operation *op, StringRef expectedMacro)
If op is an sv.ifdef/sv.ifdef.procedural whose macro matches expectedMacro, returns its else region; ...
static bool processBlockIfdef(Block &block, StringRef macro)
ifdef mode: wrap each masked op in its own sv.ifdef/sv.ifdef.procedural.
static StringAttr resolveMacroSymName(mlir::ModuleOp moduleOp, StringRef verilogName, bool &created)
Resolve the symbol name to use for the sv.macro.decl referenced by ifdef mode's sv....
static void processBlockDelete(Block &block)
delete mode: walk the block and erase every masked op.
A namespace that is used to store existing names and generate new names in some scope within the IR.
void add(mlir::ModuleOp module)
StringRef newName(const Twine &name)
Return a unique name, derived from the input name, and add the new name to the internal namespace.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
static ResultTy transformReduce(MLIRContext *context, IterTy begin, IterTy end, ResultTy init, ReduceFuncTy reduce, TransformFuncTy transform)
Wrapper for llvm::parallelTransformReduce that performs the transform_reduce serially when MLIR multi...
bool isInProceduralRegion(Operation *op)
Returns true if op has a parent marked as a procedural region that is closer than any parent marked a...