13 #ifndef CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
14 #define CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
21 #include "llvm/ADT/TypeSwitch.h"
35 SmallVector<std::pair<StringRef, StringRef>>
instances;
43 void toVector(SmallVectorImpl<char> &out)
const;
46 std::string
str()
const {
49 return std::string(out);
68 template <
typename... T>
70 if (
auto opRef = dyn_cast<OpAnnoTarget>(
ref))
71 return isa<T...>(opRef.getOp());
85 ->getParentOfType<FModuleLike>()
89 os <<
"/" << inst.getName() <<
":" << inst.getModuleName();
90 if (!path.
isOpOfType<FModuleOp, FExtModuleOp, InstanceOp>()) {
91 os <<
">" << path.
ref;
92 auto type = dyn_cast<FIRRTLBaseType>(path.
ref.
getType());
96 while (targetFieldID) {
98 .
Case<FVectorType>([&](FVectorType vector) {
99 auto index = vector.getIndexForFieldID(targetFieldID);
100 os <<
"[" << index <<
"]";
101 type = vector.getElementType();
102 targetFieldID -= vector.getFieldID(index);
104 .
template Case<BundleType>([&](BundleType bundle) {
105 auto index = bundle.getIndexForFieldID(targetFieldID);
106 os <<
"." << bundle.getElementName(index);
107 type = bundle.getElementType(index);
108 targetFieldID -= bundle.getFieldID(index);
110 .Default([&](
auto) { targetFieldID = 0; });
116 template <
typename T>
118 os << target.
getOp()->getAttrOfType<StringAttr>(
"name").getValue();
122 template <
typename T>
128 template <
typename T>
130 if (
auto op = dyn_cast<OpAnnoTarget>(target))
132 else if (
auto port = dyn_cast<PortAnnoTarget>(target))
135 os <<
"<<Unknown Anno Target>>";
155 TypeSwitch<Operation *>(op)
156 .Case<InstanceOp, MemOp, NodeOp, RegOp, RegResetOp, WireOp,
157 chirrtl::CombMemOp, chirrtl::SeqMemOp, chirrtl::MemoryPortOp,
158 chirrtl::MemoryDebugPortOp, PrintFOp>([&](
auto op) {
160 if (
auto name = op.getNameAttr(); name && !name.getValue().empty())
168 if (
auto name = oldOp->getAttrOfType<StringAttr>(
"name");
169 name && !name.getValue().empty())
176 targets.insert({mod.getPortNameAttr(portNo),
PortAnnoTarget(mod, portNo)});
181 void gatherTargets(FModuleLike mod);
183 llvm::DenseMap<StringRef, AnnoTarget>
targets;
191 auto it = targetCaches.find(module);
192 if (it == targetCaches.end())
193 it = targetCaches.try_emplace(module, module).first;
199 return getOrCreateCacheFor(module).getTargetForName(name);
208 auto mod = newOp->getParentOfType<FModuleOp>();
209 auto it = targetCaches.find(mod);
210 if (it == targetCaches.end())
212 it->getSecond().replaceOp(oldOp, newOp);
217 auto it = targetCaches.find(mod);
218 if (it == targetCaches.end())
220 it->getSecond().insertPort(mod, portNo);
225 auto mod = op->getParentOfType<FModuleOp>();
226 auto it = targetCaches.find(mod);
227 if (it == targetCaches.end())
229 it->getSecond().insertOp(op);
242 std::optional<TokenAnnoTarget>
tokenizePath(StringRef origTarget);
252 std::optional<AnnoPathValue>
resolvePath(StringRef rawPath, CircuitOp circuit,
312 hw::HierPathOp getOpFor(ArrayAttr attr);
315 return getOpFor(attr).getSymNameAttr();
326 DenseMap<ArrayAttr, hw::HierPathOp>
cache;
336 : circuit(circuit), symTbl(symTbl), addToWorklistFn(addToWorklistFn),
337 instancePathCache(instancePathCache), hierPathCache(circuit, symTbl),
338 noRefTypePorts(noRefTypePorts) {}
346 size_t numReusedHierPaths = 0;
356 return namespaces[module];
366 unsigned annotationID = 0;
391 template <
typename A>
392 A
tryGetAs(DictionaryAttr &dict,
const Attribute &root, StringRef key,
393 Location loc, Twine className, Twine path = Twine()) {
395 auto value = dict.get(key);
397 SmallString<128> msg;
398 if (path.isTriviallyEmpty())
399 msg = (
"Annotation '" + className +
"' did not contain required key '" +
403 msg = (
"Annotation '" + className +
"' with path '" + path +
404 "' did not contain required key '" + key +
"'.")
406 mlir::emitError(loc, msg).attachNote()
407 <<
"The full Annotation is reproduced here: " << root <<
"\n";
411 auto valueA = dyn_cast_or_null<A>(value);
413 SmallString<128> msg;
414 if (path.isTriviallyEmpty())
415 msg = (
"Annotation '" + className +
416 "' did not contain the correct type for key '" + key +
"'.")
419 msg = (
"Annotation '" + className +
"' with path '" + path +
420 "' did not contain the correct type for key '" + key +
"'.")
422 mlir::emitError(loc, msg).attachNote()
423 <<
"The full Annotation is reproduced here: " << root <<
"\n";
436 CircuitTargetCache *targetCaches =
nullptr);
444 llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr,
ApplyState &)>
446 llvm::function_ref<LogicalResult(
const AnnoPathValue &, DictionaryAttr,
454 const std::function<
void(llvm::Twine)> &errorHandler = {});
463 std::optional<AnnoPathValue>
stdResolve(DictionaryAttr anno, ApplyState &state);
466 std::optional<AnnoPathValue>
tryResolve(DictionaryAttr anno, ApplyState &state);
475 DictionaryAttr anno, ApplyState &state,
481 template <
bool allowNonLocal,
bool allowPortAnnoTarget,
typename T,
486 if (isa<PortAnnoTarget>(target.
ref)) {
487 if (!allowPortAnnoTarget)
495 template <
bool allowNonLocal,
typename T,
typename... Tr>
505 template <
bool allowNonLocal = false>
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.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Direction
The direction of a Component or Cell port.
LogicalResult applyOMIR(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Main entry point to handle scattering of an OMIRAnnotation.
igraph::InstancePathCache InstancePathCache
static LogicalResult applyWithoutTarget(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
An applier which puts the annotation on the target and drops the 'target' field from the annotaiton.
std::optional< AnnoPathValue > stdResolve(DictionaryAttr anno, ApplyState &state)
===-------------------------------------------------------------------—===// Standard Utility Resolve...
A tryGetAs(DictionaryAttr &dict, const Attribute &root, StringRef key, Location loc, Twine className, Twine path=Twine())
Implements the same behavior as DictionaryAttr::getAs<A> to return the value of a specific type assoc...
std::optional< AnnoPathValue > resolveEntities(TokenAnnoTarget path, CircuitOp circuit, SymbolTable &symTbl, CircuitTargetCache &cache)
Convert a parsed target string to a resolved target structure.
std::string canonicalizeTarget(StringRef target)
Return an input target string in canonical form.
InstanceOp addPortsToModule(FModuleLike mod, InstanceOp instOnPath, FIRRTLType portType, Direction dir, StringRef newName, InstancePathCache &instancePathcache, CircuitTargetCache *targetCaches=nullptr)
Add ports to the module and all its instances and return the clone for instOnPath.
LogicalResult applyGCTMemTaps(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
LogicalResult applyWiring(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Consume SourceAnnotation and SinkAnnotation, storing into state.
LogicalResult applyTraceName(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Expand a TraceNameAnnotation (which has don't touch semantics) into a TraceAnnotation (which does NOT...
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const InstanceInfo::LatticeValue &value)
LogicalResult registerAnnotationRecord(StringRef annoClass, AnnoRecord annoRecord, const std::function< void(llvm::Twine)> &errorHandler={})
Register external annotation records.
LogicalResult applyGCTDataTaps(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
std::optional< AnnoPathValue > resolvePath(StringRef rawPath, CircuitOp circuit, SymbolTable &symTbl, CircuitTargetCache &cache)
Resolve a string path to a named item inside a circuit.
LogicalResult applyGCTView(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
std::optional< TokenAnnoTarget > tokenizePath(StringRef origTarget)
Parse a FIRRTL annotation path into its constituent parts.
LogicalResult applyWithoutTargetImpl(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state, bool allowNonLocal)
===-------------------------------------------------------------------—===// Standard Utility Applier...
std::optional< AnnoPathValue > tryResolve(DictionaryAttr anno, ApplyState &state)
Resolves with target, if it exists. If not, resolves to the circuit.
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.
SmallVector< InstanceOp > instances
AnnoPathValue(const SmallVectorImpl< InstanceOp > &insts, AnnoTarget b, unsigned fieldIdx)
AnnoPathValue(CircuitOp op)
AnnoPathValue(Operation *op)
===-------------------------------------------------------------------—===// LowerAnnotations ===----...
llvm::function_ref< LogicalResult(const AnnoPathValue &, DictionaryAttr, ApplyState &)> applier
llvm::function_ref< std::optional< AnnoPathValue >DictionaryAttr, ApplyState &)> resolver
Cache AnnoTargets for a module's named things.
AnnoTarget getTargetForName(StringRef name) const
Lookup the target for 'name', empty if not found.
AnnoTargetCache(FModuleLike mod)
AnnoTargetCache(AnnoTargetCache &&other)
void gatherTargets(FModuleLike mod)
Walk the module and add named things to 'targets'.
void insertOp(Operation *op)
AnnoTargetCache(const AnnoTargetCache &other)=default
void replaceOp(Operation *oldOp, Operation *newOp)
Replace oldOp with newOp in the target cache.
void insertPort(FModuleLike mod, size_t portNo)
Add a new module port to the target cache.
llvm::DenseMap< StringRef, AnnoTarget > targets
An annotation target is used to keep track of something that is targeted by an Annotation.
FIRRTLType getType() const
Get the type of the target.
Operation * getOp() const
FModuleLike getModule() const
Get the parent module of the target.
State threaded through functions for resolving and applying annotations.
HierPathCache hierPathCache
DenseSet< InstanceOp > wiringProblemInstRefs
hw::InnerSymbolNamespace & getNamespace(FModuleLike module)
DenseMap< StringAttr, LegacyWiringProblem > legacyWiringProblems
ApplyState(CircuitOp circuit, SymbolTable &symTbl, AddToWorklistFn addToWorklistFn, InstancePathCache &instancePathCache, bool noRefTypePorts)
SmallVector< WiringProblem > wiringProblems
AddToWorklistFn addToWorklistFn
InstancePathCache & instancePathCache
CircuitTargetCache targetCaches
hw::InnerSymbolNamespaceCollection namespaces
llvm::function_ref< void(DictionaryAttr)> AddToWorklistFn
Cache AnnoTargets for a circuit's modules, walked as needed.
DenseMap< Operation *, AnnoTargetCache > targetCaches
void replaceOp(Operation *oldOp, Operation *newOp)
Replace oldOp with newOp in the target cache.
void invalidate()
Clear the cache completely.
void insertPort(FModuleLike mod, size_t portNo)
Add a new module port to the target cache.
const AnnoTargetCache & getOrCreateCacheFor(FModuleLike module)
Get cache for specified module, creating it as needed.
void insertOp(Operation *op)
Add a new op to the target cache.
AnnoTarget lookup(FModuleLike module, StringRef name)
Lookup the target for 'name' in 'module'.
A cache of existing HierPathOps, mostly used to facilitate HierPathOp reuse.
DenseMap< ArrayAttr, hw::HierPathOp > cache
StringAttr getSymFor(ArrayAttr attr)
FlatSymbolRefAttr getRefFor(ArrayAttr attr)
SymbolTable & symbolTable
const SymbolTable & getSymbolTable() const
A representation of a legacy Wiring problem consisting of a signal source that should be connected to...
SmallVector< Value > sinks
Sink(s) to wire to.
Value source
A source to wire from.
A store of pending modifications to a FIRRTL module associated with solving one or more WiringProblem...
SmallVector< portInfoPair > portsToAdd
Ports that should be added to a module.
std::pair< size_t, PortInfo > portInfoPair
A pair of Wiring Problem index and port information.
SmallVector< uturnPair > uturns
A secondary value that may need to be hooked up.
DenseMap< size_t, Value > connectionMap
A mapping of a Value that should be connected to either a new port or a U-turn, for a specific Wiring...
std::pair< size_t, Value > uturnPair
A pair of Wiring Problem index and a U-turn Value that should be connected.
This represents an annotation targeting a specific operation.
This represents an annotation targeting a specific port of a module, memory, or instance.
unsigned getPortNo() const
Stores an index into an aggregate.
The parsed annotation path.
SmallVector< TargetToken > component
std::string str() const
Convert the annotation path to a string.
void toVector(SmallVectorImpl< char > &out) const
Append the annotation path to the given SmallString or SmallVector.
SmallVector< std::pair< StringRef, StringRef > > instances
A representation of a deferred Wiring problem consisting of a source that should be connected to a si...
Value source
A source to wire from.
Value sink
A sink to wire to.
RefTypeUsage refTypeUsage
The usage of ref type ports when solving this problem.
std::string newNameHint
A base name to use when generating new signals associated with this wiring problem.
A data structure that caches and provides absolute paths to module instances in the IR.