25 #include "mlir/IR/ImplicitLocOpBuilder.h"
26 #include "mlir/Pass/Pass.h"
27 #include "llvm/ADT/APSInt.h"
28 #include "llvm/ADT/TypeSwitch.h"
29 #include "llvm/Support/Debug.h"
31 #define DEBUG_TYPE "firrtl-remove-resets"
35 #define GEN_PASS_DEF_SFCCOMPAT
36 #include "circt/Dialect/FIRRTL/Passes.h.inc"
40 using namespace circt;
41 using namespace firrtl;
45 void runOnOperation()
override;
50 llvm::dbgs() <<
"==----- Running SFCCompat "
51 "---------------------------------------------------===\n"
52 <<
"Module: '" << getOperation().
getName() <<
"'\n";);
54 bool madeModifications =
false;
55 SmallVector<InvalidValueOp> invalidOps;
58 auto isFullResetAnno = [fullResetAttr](
Annotation anno) {
59 auto annoClassAttr = anno.getClassAttr();
60 return annoClassAttr == fullResetAttr;
64 [&](
unsigned argNum,
Annotation anno) {
return isFullResetAnno(anno); });
65 getOperation()->walk([isFullResetAnno, &fullResetExists](Operation *op) {
68 madeModifications |= fullResetExists;
70 auto result = getOperation()->walk([&](Operation *op) {
72 if (
auto inv = dyn_cast<InvalidValueOp>(op)) {
73 invalidOps.push_back(inv);
74 return WalkResult::advance();
76 auto reg = dyn_cast<RegResetOp>(op);
78 return WalkResult::advance();
82 if (!fullResetExists &&
walkDrivers(
reg.getResetValue(),
true,
true,
false,
84 return src.isa<InvalidValueOp>();
86 ImplicitLocOpBuilder builder(
reg.getLoc(),
reg);
87 RegOp newReg = builder.create<RegOp>(
88 reg.getResult().getType(),
reg.getClockVal(),
reg.getNameAttr(),
89 reg.getNameKindAttr(),
reg.getAnnotationsAttr(),
90 reg.getInnerSymAttr(),
reg.getForceableAttr());
91 reg.replaceAllUsesWith(newReg);
93 madeModifications =
true;
94 return WalkResult::advance();
100 if (!isa<AsyncResetType>(
reg.getResetSignal().getType()))
101 return WalkResult::advance();
103 reg.getResetValue(),
true,
true,
true,
105 if (src.isa<ConstantOp, InvalidValueOp, SpecialConstantOp,
106 AggregateConstantOp>())
108 auto diag = emitError(reg.getLoc());
109 auto [fieldName, rootKnown] = getFieldName(dst);
110 diag <<
"register " << reg.getNameAttr()
111 <<
" has an async reset, but its reset value";
113 diag <<
" \"" << fieldName <<
"\"";
114 diag <<
" is not driven with a constant value through wires, "
115 "nodes, or connects";
116 std::tie(fieldName, rootKnown) = getFieldName(src);
117 diag.attachNote(src.getLoc())
118 <<
"reset driver is "
119 << (rootKnown ? (
"\"" + fieldName +
"\"") :
"here");
122 return WalkResult::advance();
123 return WalkResult::interrupt();
126 if (result.wasInterrupted())
127 return signalPassFailure();
130 for (
auto inv : invalidOps) {
132 if (inv->getUses().empty()) {
134 madeModifications =
true;
137 ImplicitLocOpBuilder builder(inv.getLoc(), inv);
140 .
Case<ClockType, AsyncResetType, ResetType>(
141 [&](
auto type) -> Value {
142 return builder.create<SpecialConstantOp>(
143 type, builder.getBoolAttr(
false));
145 .Case<IntType>([&](
IntType type) -> Value {
148 .Case<BundleType, FVectorType>([&](
auto type) -> Value {
151 auto zero = builder.create<ConstantOp>(APSInt(*
width));
152 return builder.create<BitCastOp>(type, zero);
155 llvm_unreachable(
"all types are supported");
158 inv.replaceAllUsesWith(replacement);
160 madeModifications =
true;
163 if (!madeModifications)
164 return markAllAnalysesPreserved();
168 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