25 #include "mlir/IR/ImplicitLocOpBuilder.h"
26 #include "mlir/Pass/Pass.h"
27 #include "llvm/Support/Debug.h"
29 #define DEBUG_TYPE "firrtl-remove-resets"
33 #define GEN_PASS_DEF_SFCCOMPAT
34 #include "circt/Dialect/FIRRTL/Passes.h.inc"
38 using namespace circt;
39 using namespace firrtl;
43 void runOnOperation()
override;
48 llvm::dbgs() <<
"==----- Running SFCCompat "
49 "---------------------------------------------------===\n"
50 <<
"Module: '" << getOperation().
getName() <<
"'\n";);
52 bool madeModifications =
false;
53 SmallVector<InvalidValueOp> invalidOps;
56 auto isFullResetAnno = [fullResetAttr](
Annotation anno) {
57 auto annoClassAttr = anno.getClassAttr();
58 return annoClassAttr == fullResetAttr;
62 [&](
unsigned argNum,
Annotation anno) {
return isFullResetAnno(anno); });
63 getOperation()->walk([isFullResetAnno, &fullResetExists](Operation *op) {
66 madeModifications |= fullResetExists;
68 auto result = getOperation()->walk([&](Operation *op) {
70 if (
auto inv = dyn_cast<InvalidValueOp>(op)) {
71 invalidOps.push_back(inv);
72 return WalkResult::advance();
74 auto reg = dyn_cast<RegResetOp>(op);
76 return WalkResult::advance();
80 if (!fullResetExists &&
walkDrivers(
reg.getResetValue(),
true,
true,
false,
82 return src.isa<InvalidValueOp>();
84 ImplicitLocOpBuilder builder(
reg.getLoc(),
reg);
85 RegOp newReg = builder.create<RegOp>(
86 reg.getResult().getType(),
reg.getClockVal(),
reg.getNameAttr(),
87 reg.getNameKindAttr(),
reg.getAnnotationsAttr(),
88 reg.getInnerSymAttr(),
reg.getForceableAttr());
89 reg.replaceAllUsesWith(newReg);
91 madeModifications =
true;
92 return WalkResult::advance();
98 if (!isa<AsyncResetType>(
reg.getResetSignal().getType()))
99 return WalkResult::advance();
101 reg.getResetValue(),
true,
true,
true,
103 if (src.isa<ConstantOp, InvalidValueOp, SpecialConstantOp,
104 AggregateConstantOp>())
106 auto diag = emitError(reg.getLoc());
107 auto [fieldName, rootKnown] = getFieldName(dst);
108 diag <<
"register " << reg.getNameAttr()
109 <<
" has an async reset, but its reset value";
111 diag <<
" \"" << fieldName <<
"\"";
112 diag <<
" is not driven with a constant value through wires, "
113 "nodes, or connects";
114 std::tie(fieldName, rootKnown) = getFieldName(src);
115 diag.attachNote(src.getLoc())
116 <<
"reset driver is "
117 << (rootKnown ? (
"\"" + fieldName +
"\"") :
"here");
120 return WalkResult::advance();
121 return WalkResult::interrupt();
124 if (result.wasInterrupted())
125 return signalPassFailure();
128 for (
auto inv : invalidOps) {
130 if (inv->getUses().empty()) {
132 madeModifications =
true;
135 ImplicitLocOpBuilder builder(inv.getLoc(), inv);
138 .
Case<ClockType, AsyncResetType, ResetType>(
139 [&](
auto type) -> Value {
140 return builder.create<SpecialConstantOp>(
141 type, builder.getBoolAttr(
false));
143 .Case<IntType>([&](
IntType type) -> Value {
146 .Case<BundleType, FVectorType>([&](
auto type) -> Value {
148 assert(width &&
"width must be inferred");
149 auto zero = builder.create<ConstantOp>(APSInt(*width));
150 return builder.create<BitCastOp>(type, zero);
153 llvm_unreachable(
"all types are supported");
156 inv.replaceAllUsesWith(replacement);
158 madeModifications =
true;
161 if (!madeModifications)
162 return markAllAnalysesPreserved();
166 return std::make_unique<SFCCompatPass>();
assert(baseType &&"element must be base type")
This class represents a reference to a specific field or element of an aggregate value.
bool removeAnnotations(llvm::function_ref< bool(Annotation)> predicate)
Remove all annotations from this annotation set for which predicate returns true.
static bool removePortAnnotations(Operation *module, llvm::function_ref< bool(unsigned, Annotation)> predicate)
Remove all port annotations from a module or extmodule for which predicate returns true.
This class provides a read-only projection of an annotation.
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
This is the common base class between SIntType and UIntType.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
constexpr const char * fullResetAnnoClass
Annotation that marks a reset (port or wire) and domain.
std::unique_ptr< mlir::Pass > createSFCCompatPass()
bool walkDrivers(FIRRTLBaseValue value, bool lookThroughWires, bool lookThroughNodes, bool lookThroughCasts, WalkDriverCallback callback)
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
IntegerAttr getIntZerosAttr(Type type)
Utility for generating a constant zero attribute.
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
void runOnOperation() override