16#include "mlir/IR/Matchers.h"
17#include "llvm/Support/Debug.h"
19#define DEBUG_TYPE "llhd-sig2reg"
23#define GEN_PASS_DEF_SIG2REGPASS
24#include "circt/Dialect/LLHD/LLHDPasses.h.inc"
33struct Sig2RegPass :
public llhd::impl::Sig2RegPassBase<Sig2RegPass> {
34 void runOnOperation()
override;
35 void promote(SignalOp op);
36 SmallVector<SignalOp> signalsToErase;
40void Sig2RegPass::runOnOperation() {
41 LLVM_DEBUG(llvm::dbgs() <<
"Promoting signals to values in "
42 << getOperation().getModuleName() <<
"\n");
43 for (
auto op : getOperation().getOps<SignalOp>())
45 for (
auto op : signalsToErase)
47 signalsToErase.clear();
50void Sig2RegPass::promote(SignalOp op) {
54 bool multipleDrives =
false;
55 bool anyProbe =
false;
56 for (
auto *user : op->getUsers()) {
57 if (isa<ProbeOp>(user)) {
62 if (
auto driveOp = dyn_cast<DriveLikeOp>(user)) {
63 if (driveOp->getBlock() != op->getBlock()) {
64 LLVM_DEBUG(llvm::dbgs() <<
"- Skipping " << op
65 <<
" (driven from different block)\n");
70 multipleDrives =
true;
76 LLVM_DEBUG(llvm::dbgs() <<
"- Skipping " << op <<
" (unsupported user "
77 << user->getName() <<
")\n");
84 LLVM_DEBUG(llvm::dbgs() <<
"- Removing unprobed " << op <<
"\n");
86 SmallPtrSet<Operation *, 8> erased;
87 for (
auto *user : llvm::make_early_inc_range(op->getUsers()))
88 if (erased.insert(user).second)
90 signalsToErase.push_back(op);
97 LLVM_DEBUG(llvm::dbgs() <<
"- Skipping " << op <<
" (multiple drives)\n");
103 if (drive && drive.getEnable()) {
104 LLVM_DEBUG(llvm::dbgs() <<
"- Skipping " << op <<
" (conditional drive)\n");
112 value = drive.getValue();
113 if (drive.getTime()) {
115 LLVM_DEBUG(llvm::dbgs()
116 <<
"- Skipping " << op
117 <<
" (delayed drive to signal with initializer)\n");
122 if (!matchPattern(drive.getTime(), m_Constant(&delay))) {
123 LLVM_DEBUG(llvm::dbgs()
124 <<
"- Skipping " << op <<
" (non-constant drive delay)\n");
128 OpBuilder builder(drive);
129 value = DelayOp::create(builder, drive.getLoc(), value, delay);
132 value = op.getInit();
134 LLVM_DEBUG(llvm::dbgs()
135 <<
"- Skipping " << op <<
" (undriven with no initializer)\n");
142 if (!matchPattern(value, m_Constant())) {
143 LLVM_DEBUG(llvm::dbgs() <<
"- Skipping " << op
144 <<
" (undriven with non-constant initializer)\n");
153 llvm::dbgs() <<
"- Replacing " << op <<
" with ";
154 value.printAsOperand(llvm::dbgs(), OpPrintingFlags());
155 llvm::dbgs() <<
"\n";
157 SmallPtrSet<Operation *, 8> erased;
158 for (
auto *user : llvm::make_early_inc_range(op->getUsers())) {
159 if (
auto probeOp = dyn_cast<ProbeOp>(user))
160 probeOp.replaceAllUsesWith(value);
161 if (erased.insert(user).second)
164 signalsToErase.push_back(op);
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.