15 #include "mlir/IR/ImplicitLocOpBuilder.h"
16 #include "mlir/Pass/Pass.h"
17 #include "llvm/Support/Debug.h"
20 #define DEBUG_TYPE "arc-strip-sv"
24 #define GEN_PASS_DEF_STRIPSV
25 #include "circt/Dialect/Arc/ArcPasses.h.inc"
29 using namespace circt;
33 struct StripSVPass :
public arc::impl::StripSVBase<StripSVPass> {
34 void runOnOperation()
override;
35 SmallVector<Operation *> opsToDelete;
36 SmallPtrSet<StringAttr, 4> clockGateModuleNames;
40 void StripSVPass::runOnOperation() {
41 auto mlirModule = getOperation();
43 clockGateModuleNames.clear();
45 auto expectedClockGateInputs =
49 auto expectedClockGateOutputs =
54 if (extModOp.getVerilogModuleName() ==
"EICG_wrapper") {
55 if (!llvm::equal(extModOp.getInputNames(), expectedClockGateInputs) ||
56 !llvm::equal(extModOp.getOutputNames(), expectedClockGateOutputs)) {
57 extModOp.emitError(
"clock gate module `")
58 << extModOp.getModuleName() <<
"` has incompatible port names "
59 << extModOp.getInputNames() <<
" -> " << extModOp.getOutputNames();
60 return signalPassFailure();
62 if (!llvm::equal(extModOp.getInputTypes(),
63 ArrayRef<Type>{i1Type, i1Type, i1Type}) ||
64 !llvm::equal(extModOp.getOutputTypes(), ArrayRef<Type>{i1Type})) {
65 extModOp.emitError(
"clock gate module `")
66 << extModOp.getModuleName() <<
"` has incompatible port types "
67 << extModOp.getInputTypes() <<
" -> " << extModOp.getOutputTypes();
68 return signalPassFailure();
70 clockGateModuleNames.insert(extModOp.getModuleNameAttr());
71 opsToDelete.push_back(extModOp);
75 LLVM_DEBUG(
llvm::dbgs() <<
"Found " << clockGateModuleNames.size()
79 for (
auto &op : llvm::make_early_inc_range(*mlirModule.getBody()))
80 if (isa<om::OMDialect>(op.getDialect()))
84 mlirModule.walk([](Operation *op) {
85 auto isSVAttr = [](NamedAttribute attr) {
86 return attr.getName().getValue().startswith(
"sv.");
88 if (llvm::any_of(op->getAttrs(), isSVAttr)) {
89 SmallVector<NamedAttribute> newAttrs;
90 newAttrs.reserve(op->getAttrs().size());
91 for (
auto attr : op->getAttrs())
93 newAttrs.push_back(attr);
94 op->setAttrs(newAttrs);
99 for (
auto verb : mlirModule.getOps<sv::VerbatimOp>())
100 opsToDelete.push_back(verb);
102 opsToDelete.push_back(verb);
103 for (
auto verb : mlirModule.getOps<sv::MacroDeclOp>())
104 opsToDelete.push_back(verb);
107 for (Operation &op : *module.getBodyBlock()) {
109 if (isa<sv::IfDefOp, sv::CoverOp, sv::CoverConcurrentOp>(&op)) {
110 opsToDelete.push_back(&op);
113 if (isa<sv::VerbatimOp, sv::AlwaysOp>(&op)) {
114 opsToDelete.push_back(&op);
119 if (
auto assign = dyn_cast<sv::AssignOp>(&op)) {
120 auto wire = assign.getDest().getDefiningOp<
sv::WireOp>();
122 assign.emitOpError(
"expected wire lhs");
123 return signalPassFailure();
125 for (Operation *user : wire->getUsers()) {
128 auto readInout = dyn_cast<sv::ReadInOutOp>(user);
130 user->emitOpError(
"has user that is not `sv.read_inout`");
131 return signalPassFailure();
133 readInout.replaceAllUsesWith(assign.getSrc());
134 opsToDelete.push_back(readInout);
136 opsToDelete.push_back(assign);
137 opsToDelete.push_back(wire);
142 if (
auto reg = dyn_cast<seq::FirRegOp>(&op)) {
148 reg.getResetValue(),
reg.getNext(),
151 next =
reg.getNext();
154 reg.getLoc(), next.getType(), next,
reg.getClk(),
reg.getNameAttr(),
155 Value{}, Value{}, Value{},
reg.getInnerSymAttr());
156 reg.replaceAllUsesWith(compReg);
157 opsToDelete.push_back(
reg);
163 if (
auto instOp = dyn_cast<hw::InstanceOp>(&op)) {
164 auto modName = instOp.getModuleNameAttr().getAttr();
165 ImplicitLocOpBuilder
builder(instOp.getLoc(), instOp);
166 if (clockGateModuleNames.contains(modName)) {
168 instOp.getOperand(1), instOp.getOperand(2),
true);
170 builder.create<arc::ClockGateOp>(instOp.getOperand(0), enable);
171 instOp.replaceAllUsesWith(gated);
172 opsToDelete.push_back(instOp);
178 for (
auto *op : opsToDelete)
183 return std::make_unique<StripSVPass>();
std::unique_ptr< mlir::Pass > createStripSVPass()
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
mlir::raw_indented_ostream & dbgs()
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)