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);
56 return StringAttr::get(context, out);
75 template <
typename... T>
77 if (
auto opRef = dyn_cast<OpAnnoTarget>(
ref))
78 return isa<T...>(opRef.getOp());
85 os <<
"~" << path.
ref.
getModule()->getParentOfType<CircuitOp>().getName()
92 ->getParentOfType<FModuleLike>()
96 os <<
"/" << inst.getName() <<
":" << inst.getModuleName();
97 if (!path.
isOpOfType<FModuleOp, FExtModuleOp, InstanceOp>()) {
98 os <<
">" << path.
ref;
99 auto type = dyn_cast<FIRRTLBaseType>(path.
ref.
getType());
103 while (targetFieldID) {
105 .
Case<FVectorType>([&](FVectorType vector) {
106 auto index = vector.getIndexForFieldID(targetFieldID);
107 os <<
"[" << index <<
"]";
108 type = vector.getElementType();
109 targetFieldID -= vector.getFieldID(index);
111 .
template Case<BundleType>([&](BundleType bundle) {
112 auto index = bundle.getIndexForFieldID(targetFieldID);
113 os <<
"." << bundle.getElementName(index);
114 type = bundle.getElementType(index);
115 targetFieldID -= bundle.getFieldID(index);
117 .Default([&](
auto) { targetFieldID = 0; });
125 os << target.
getOp()->getAttrOfType<StringAttr>(
"name").getValue();
137 if (
auto op = dyn_cast<OpAnnoTarget>(target))
139 else if (
auto port = dyn_cast<PortAnnoTarget>(target))
142 os <<
"<<Unknown Anno Target>>";
162 TypeSwitch<Operation *>(op)
163 .Case<InstanceOp, MemOp, NodeOp, RegOp, RegResetOp, WireOp,
164 chirrtl::CombMemOp, chirrtl::SeqMemOp, chirrtl::MemoryPortOp,
165 chirrtl::MemoryDebugPortOp, PrintFOp, FPrintFOp>([&](
auto op) {
167 if (
auto name = op.getNameAttr(); name && !name.getValue().empty())
175 if (
auto name = oldOp->getAttrOfType<StringAttr>(
"name");
176 name && !name.getValue().empty())
183 targets.insert({mod.getPortNameAttr(portNo),
PortAnnoTarget(mod, portNo)});
188 void gatherTargets(FModuleLike mod);
190 llvm::DenseMap<StringRef, AnnoTarget>
targets;
198 auto it = targetCaches.find(module);
199 if (it == targetCaches.end())
200 it = targetCaches.try_emplace(module, module).first;
206 return getOrCreateCacheFor(module).getTargetForName(name);
215 auto mod = newOp->getParentOfType<FModuleOp>();
216 auto it = targetCaches.find(mod);
217 if (it == targetCaches.end())
219 it->getSecond().replaceOp(oldOp, newOp);
224 auto it = targetCaches.find(mod);
225 if (it == targetCaches.end())
227 it->getSecond().insertPort(mod, portNo);
232 auto mod = op->getParentOfType<FModuleOp>();
233 auto it = targetCaches.find(mod);
234 if (it == targetCaches.end())
236 it->getSecond().insertOp(op);
249std::optional<TokenAnnoTarget>
tokenizePath(StringRef origTarget);
259std::optional<AnnoPathValue>
resolvePath(StringRef rawPath, CircuitOp circuit,
319 hw::HierPathOp getOpFor(ArrayAttr attr);
322 return getOpFor(attr).getSymNameAttr();
326 return FlatSymbolRefAttr::get(getSymFor(attr));
333 DenseMap<ArrayAttr, hw::HierPathOp>
cache;
343 : circuit(circuit), symTbl(symTbl), addToWorklistFn(addToWorklistFn),
344 instancePathCache(instancePathCache), hierPathCache(circuit, symTbl),
345 noRefTypePorts(noRefTypePorts) {}
353 size_t numReusedHierPaths = 0;
363 return namespaces[module];
367 return IntegerAttr::get(IntegerType::get(circuit.getContext(), 64),
373 unsigned annotationID = 0;
396A
tryGetAsBase(DictionaryAttr dict, Attribute root, StringRef key, Location loc,
397 Twine whatSpecific, Twine whatFull, Twine path = Twine()) {
398 SmallString<128> msg;
400 auto value = dict.get(key);
402 if (path.isTriviallyEmpty())
403 (whatSpecific +
" did not contain required key '" + key +
"'.")
406 (whatSpecific +
" with path '" + path +
407 "' did not contain required key '" + key +
"'.")
409 mlir::emitError(loc, msg).attachNote()
410 <<
"The full " << whatFull <<
" is reproduced here: " << root;
414 auto valueA = dyn_cast<A>(value);
416 if (path.isTriviallyEmpty())
417 (whatSpecific +
" did not contain the correct type for key '" + key +
421 (whatSpecific +
" with path '" + path +
422 "' did not contain the correct type for key '" + key +
"'.")
424 mlir::emitError(loc, msg).attachNote()
425 <<
"The full " << whatFull <<
" is reproduced here: " << root;
436A
tryGetAs(DictionaryAttr dict, Attribute root, StringRef key, Location loc,
437 Twine clazz, Twine path = Twine()) {
438 return tryGetAsBase<A>(dict, root, key, loc,
"Annotation '" + clazz +
"'",
445InstanceOp addPortsToModule(FModuleLike mod, InstanceOp instOnPath,
446 FIRRTLType portType, Direction dir,
448 InstancePathCache &instancePathcache,
449 CircuitTargetCache *targetCaches =
nullptr);
457 llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr,
ApplyState &)>
459 llvm::function_ref<LogicalResult(
const AnnoPathValue &, DictionaryAttr,
467 const std::function<
void(llvm::Twine)> &errorHandler = {});
476std::optional<AnnoPathValue> stdResolve(DictionaryAttr anno, ApplyState &state);
479std::optional<AnnoPathValue> tryResolve(DictionaryAttr anno, ApplyState &state);
487LogicalResult applyWithoutTargetImpl(
const AnnoPathValue &target,
488 DictionaryAttr anno, ApplyState &state,
494template <
bool allowNonLocal,
bool allowPortAnnoTarget,
typename T,
499 if (isa<PortAnnoTarget>(target.
ref)) {
500 if (!allowPortAnnoTarget)
508template <
bool allowNonLocal,
typename T,
typename... Tr>
518template <
bool allowNonLocal = false>
static std::vector< mlir::Value > toVector(mlir::ValueRange range)
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.
A tryGetAs(DictionaryAttr dict, Attribute root, StringRef key, Location loc, Twine clazz, 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.
LogicalResult applyGCTMemTaps(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const InstanceInfo::LatticeValue &value)
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 annotation.
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...
A tryGetAsBase(DictionaryAttr dict, Attribute root, StringRef key, Location loc, Twine whatSpecific, Twine whatFull, Twine path=Twine())
Implements the same behavior as DictionaryAttr::getAs<A> to return the value of a specific type assoc...
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< std::optional< AnnoPathValue >(DictionaryAttr, ApplyState &)> resolver
llvm::function_ref< LogicalResult(const AnnoPathValue &, DictionaryAttr, ApplyState &)> applier
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
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
hw::InnerSymbolNamespace & getNamespace(FModuleLike module)
llvm::function_ref< void(DictionaryAttr)> AddToWorklistFn
Cache AnnoTargets for a circuit's modules, walked as needed.
const AnnoTargetCache & getOrCreateCacheFor(FModuleLike module)
Get cache for specified module, creating it 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.
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)
const SymbolTable & getSymbolTable() const
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.
StringAttr toStringAttr(MLIRContext *context) const
Convert the annotation path to a StringAttr.
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 paths to module instances in the IR.