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>
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>
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();
324 DenseMap<ArrayAttr, hw::HierPathOp>
cache;
334 : circuit(circuit), symTbl(symTbl), addToWorklistFn(addToWorklistFn),
335 instancePathCache(instancePathCache), hierPathCache(circuit, symTbl),
336 noRefTypePorts(noRefTypePorts) {}
344 size_t numReusedHierPaths = 0;
354 return namespaces[module];
364 unsigned annotationID = 0;
389 template <
typename A>
390 A
tryGetAs(DictionaryAttr &dict,
const Attribute &root, StringRef key,
391 Location loc, Twine className, Twine path = Twine()) {
393 auto value = dict.get(key);
395 SmallString<128> msg;
396 if (path.isTriviallyEmpty())
397 msg = (
"Annotation '" + className +
"' did not contain required key '" +
401 msg = (
"Annotation '" + className +
"' with path '" + path +
402 "' did not contain required key '" + key +
"'.")
404 mlir::emitError(loc, msg).attachNote()
405 <<
"The full Annotation is reproduced here: " << root <<
"\n";
409 auto valueA = dyn_cast_or_null<A>(
value);
411 SmallString<128> msg;
412 if (path.isTriviallyEmpty())
413 msg = (
"Annotation '" + className +
414 "' did not contain the correct type for key '" + key +
"'.")
417 msg = (
"Annotation '" + className +
"' with path '" + path +
418 "' did not contain the correct type for key '" + key +
"'.")
420 mlir::emitError(loc, msg).attachNote()
421 <<
"The full Annotation is reproduced here: " << root <<
"\n";
434 CircuitTargetCache *targetCaches =
nullptr);
442 llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr,
ApplyState &)>
444 llvm::function_ref<LogicalResult(
const AnnoPathValue &, DictionaryAttr,
452 const std::function<
void(llvm::Twine)> &errorHandler = {});
461 std::optional<AnnoPathValue>
stdResolve(DictionaryAttr anno, ApplyState &state);
464 std::optional<AnnoPathValue>
tryResolve(DictionaryAttr anno, ApplyState &state);
473 DictionaryAttr anno, ApplyState &state,
479 template <
bool allowNonLocal,
bool allowPortAnnoTarget,
typename T,
485 if (!allowPortAnnoTarget)
493 template <
bool allowNonLocal,
typename T,
typename... Tr>
503 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.
T & operator<<(T &os, FIRVersion version)
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...
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.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
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
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.