CIRCT 22.0.0git
Loading...
Searching...
No Matches
FIRRTLAnnotationHelper.h
Go to the documentation of this file.
1//===- FIRRTLAnnotationHelper.h - FIRRTL Annotation Lookup ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file declares helpers mapping annotations to operations.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
14#define CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
15
21#include "llvm/ADT/TypeSwitch.h"
22
23namespace circt {
24namespace firrtl {
25
26/// Stores an index into an aggregate.
28 StringRef name;
29 bool isIndex;
30};
31
32/// The parsed annotation path.
34 StringRef circuit;
35 SmallVector<std::pair<StringRef, StringRef>> instances;
36 StringRef module;
37 // The final name of the target
38 StringRef name;
39 // Any aggregates indexed.
40 SmallVector<TargetToken> component;
41
42 /// Append the annotation path to the given `SmallString` or `SmallVector`.
43 void toVector(SmallVectorImpl<char> &out) const;
44
45 /// Convert the annotation path to a string.
46 std::string str() const {
47 SmallString<32> out;
48 toVector(out);
49 return std::string(out);
50 }
51
52 /// Convert the annotation path to a StringAttr.
53 StringAttr toStringAttr(MLIRContext *context) const {
54 SmallString<32> out;
55 toVector(out);
56 return StringAttr::get(context, out);
57 }
58};
59
60// The potentially non-local resolved annotation.
62 SmallVector<InstanceOp> instances;
64 unsigned fieldIdx = 0;
65
66 AnnoPathValue() = default;
67 AnnoPathValue(CircuitOp op) : ref(OpAnnoTarget(op)) {}
68 AnnoPathValue(Operation *op) : ref(OpAnnoTarget(op)) {}
69 AnnoPathValue(const SmallVectorImpl<InstanceOp> &insts, AnnoTarget b,
70 unsigned fieldIdx)
71 : instances(insts.begin(), insts.end()), ref(b), fieldIdx(fieldIdx) {}
72
73 bool isLocal() const { return instances.empty(); }
74
75 template <typename... T>
76 bool isOpOfType() const {
77 if (auto opRef = dyn_cast<OpAnnoTarget>(ref))
78 return isa<T...>(opRef.getOp());
79 return false;
80 }
81};
82
83template <typename T>
84static T &operator<<(T &os, const AnnoPathValue &path) {
85 os << "~" << path.ref.getModule()->getParentOfType<CircuitOp>().getName()
86 << "|";
87
88 if (path.isLocal()) {
89 os << path.ref.getModule().getModuleName();
90 } else {
91 os << path.instances.front()
92 ->getParentOfType<FModuleLike>()
93 .getModuleName();
94 }
95 for (auto inst : path.instances)
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());
100 if (!type)
101 return os;
102 auto targetFieldID = path.fieldIdx;
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);
110 })
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);
116 })
117 .Default([&](auto) { targetFieldID = 0; });
118 }
119 }
120 return os;
121}
122
123template <typename T>
124static T &operator<<(T &os, const OpAnnoTarget &target) {
125 os << target.getOp()->getAttrOfType<StringAttr>("name").getValue();
126 return os;
127}
128
129template <typename T>
130static T &operator<<(T &os, const PortAnnoTarget &target) {
131 os << target.getModule().getPortName(target.getPortNo());
132 return os;
133}
134
135template <typename T>
136static T &operator<<(T &os, const AnnoTarget &target) {
137 if (auto op = dyn_cast<OpAnnoTarget>(target))
138 os << op;
139 else if (auto port = dyn_cast<PortAnnoTarget>(target))
140 os << port;
141 else
142 os << "<<Unknown Anno Target>>";
143 return os;
144}
145
146/// Cache AnnoTargets for a module's named things.
148 AnnoTargetCache() = delete;
149 AnnoTargetCache(const AnnoTargetCache &other) = default;
151 : targets(std::move(other.targets)) {}
152
153 AnnoTargetCache(FModuleLike mod) { gatherTargets(mod); }
154
155 /// Lookup the target for 'name', empty if not found.
156 /// (check for validity using operator bool()).
157 AnnoTarget getTargetForName(StringRef name) const {
158 return targets.lookup(name);
159 }
160
161 void insertOp(Operation *op) {
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) {
166 // To be safe, check attribute and non-empty name before adding.
167 if (auto name = op.getNameAttr(); name && !name.getValue().empty())
168 targets.insert({name, OpAnnoTarget(op)});
169 });
170 }
171
172 /// Replace `oldOp` with `newOp` in the target cache. The new and old ops can
173 /// have different names.
174 void replaceOp(Operation *oldOp, Operation *newOp) {
175 if (auto name = oldOp->getAttrOfType<StringAttr>("name");
176 name && !name.getValue().empty())
177 targets.erase(name);
178 insertOp(newOp);
179 }
180
181 /// Add a new module port to the target cache.
182 void insertPort(FModuleLike mod, size_t portNo) {
183 targets.insert({mod.getPortNameAttr(portNo), PortAnnoTarget(mod, portNo)});
184 }
185
186private:
187 /// Walk the module and add named things to 'targets'.
188 void gatherTargets(FModuleLike mod);
189
190 llvm::DenseMap<StringRef, AnnoTarget> targets;
191};
192
193/// Cache AnnoTargets for a circuit's modules, walked as needed.
195 /// Get cache for specified module, creating it as needed.
196 /// Returned reference may become invalidated by future calls.
197 const AnnoTargetCache &getOrCreateCacheFor(FModuleLike module) {
198 auto it = targetCaches.find(module);
199 if (it == targetCaches.end())
200 it = targetCaches.try_emplace(module, module).first;
201 return it->second;
202 }
203
204 /// Lookup the target for 'name' in 'module'.
205 AnnoTarget lookup(FModuleLike module, StringRef name) {
206 return getOrCreateCacheFor(module).getTargetForName(name);
207 }
208
209 /// Clear the cache completely.
210 void invalidate() { targetCaches.clear(); }
211
212 /// Replace `oldOp` with `newOp` in the target cache. The new and old ops can
213 /// have different names.
214 void replaceOp(Operation *oldOp, Operation *newOp) {
215 auto mod = newOp->getParentOfType<FModuleOp>();
216 auto it = targetCaches.find(mod);
217 if (it == targetCaches.end())
218 return;
219 it->getSecond().replaceOp(oldOp, newOp);
220 }
221
222 /// Add a new module port to the target cache.
223 void insertPort(FModuleLike mod, size_t portNo) {
224 auto it = targetCaches.find(mod);
225 if (it == targetCaches.end())
226 return;
227 it->getSecond().insertPort(mod, portNo);
228 }
229
230 /// Add a new op to the target cache.
231 void insertOp(Operation *op) {
232 auto mod = op->getParentOfType<FModuleOp>();
233 auto it = targetCaches.find(mod);
234 if (it == targetCaches.end())
235 return;
236 it->getSecond().insertOp(op);
237 }
238
239private:
240 DenseMap<Operation *, AnnoTargetCache> targetCaches;
241};
242
243/// Return an input \p target string in canonical form. This converts a Legacy
244/// Annotation (e.g., A.B.C) into a modern annotation (e.g., ~A|B>C). Trailing
245/// subfield/subindex references are preserved.
246std::string canonicalizeTarget(StringRef target);
247
248/// Parse a FIRRTL annotation path into its constituent parts.
249std::optional<TokenAnnoTarget> tokenizePath(StringRef origTarget);
250
251/// Convert a parsed target string to a resolved target structure. This
252/// resolves all names and aggregates from a parsed target.
253std::optional<AnnoPathValue> resolveEntities(TokenAnnoTarget path,
254 CircuitOp circuit,
255 SymbolTable &symTbl,
256 CircuitTargetCache &cache);
257
258/// Resolve a string path to a named item inside a circuit.
259std::optional<AnnoPathValue> resolvePath(StringRef rawPath, CircuitOp circuit,
260 SymbolTable &symTbl,
261 CircuitTargetCache &cache);
262
263/// A representation of a deferred Wiring problem consisting of a source that
264/// should be connected to a sink.
266 enum class RefTypeUsage { Prefer, Never };
267
268 /// A source to wire from.
269 Value source;
270
271 /// A sink to wire to.
272 Value sink;
273
274 /// A base name to use when generating new signals associated with this wiring
275 /// problem.
276 std::string newNameHint;
277
278 /// The usage of ref type ports when solving this problem.
280};
281
282/// A representation of a legacy Wiring problem consisting of a signal source
283/// that should be connected to one or many sinks.
285 /// A source to wire from.
286 Value source;
287
288 /// Sink(s) to wire to.
289 SmallVector<Value> sinks;
290};
291
292/// A store of pending modifications to a FIRRTL module associated with solving
293/// one or more WiringProblems.
295 /// A pair of Wiring Problem index and port information.
296 using portInfoPair = std::pair<size_t, PortInfo>;
297
298 /// A pair of Wiring Problem index and a U-turn Value that should be
299 /// connected.
300 using uturnPair = std::pair<size_t, Value>;
301
302 /// Ports that should be added to a module.
303 SmallVector<portInfoPair> portsToAdd;
304
305 /// A mapping of a Value that should be connected to either a new port or a
306 /// U-turn, for a specific Wiring Problem. This is pre-populated with the
307 /// source and sink.
308 DenseMap<size_t, Value> connectionMap;
309
310 /// A secondary value that _may_ need to be hooked up. This is always set
311 /// after the Value in the connectionMap.
312 SmallVector<uturnPair> uturns;
313};
314
315/// A cache of existing HierPathOps, mostly used to facilitate HierPathOp reuse.
317 HierPathCache(Operation *op, SymbolTable &symbolTable);
318
319 hw::HierPathOp getOpFor(ArrayAttr attr);
320
321 StringAttr getSymFor(ArrayAttr attr) {
322 return getOpFor(attr).getSymNameAttr();
323 }
324
325 FlatSymbolRefAttr getRefFor(ArrayAttr attr) {
326 return FlatSymbolRefAttr::get(getSymFor(attr));
327 }
328
329 const SymbolTable &getSymbolTable() const { return symbolTable; }
330
331private:
332 OpBuilder builder;
333 DenseMap<ArrayAttr, hw::HierPathOp> cache;
334 SymbolTable &symbolTable;
335};
336
337/// State threaded through functions for resolving and applying annotations.
339 using AddToWorklistFn = llvm::function_ref<void(DictionaryAttr)>;
340 ApplyState(CircuitOp circuit, SymbolTable &symTbl,
341 AddToWorklistFn addToWorklistFn,
342 InstancePathCache &instancePathCache, bool noRefTypePorts)
343 : circuit(circuit), symTbl(symTbl), addToWorklistFn(addToWorklistFn),
344 instancePathCache(instancePathCache), hierPathCache(circuit, symTbl),
345 noRefTypePorts(noRefTypePorts) {}
346
347 CircuitOp circuit;
348 SymbolTable &symTbl;
353 size_t numReusedHierPaths = 0;
354
355 // Options that control annotation lowering.
357
358 DenseSet<InstanceOp> wiringProblemInstRefs;
359 DenseMap<StringAttr, LegacyWiringProblem> legacyWiringProblems;
360 SmallVector<WiringProblem> wiringProblems;
361
363 return namespaces[module];
364 }
365
366 IntegerAttr newID() {
367 return IntegerAttr::get(IntegerType::get(circuit.getContext(), 64),
368 annotationID++);
369 }
370
371private:
373 unsigned annotationID = 0;
374};
375
376LogicalResult applyGCTView(const AnnoPathValue &target, DictionaryAttr anno,
377 ApplyState &state);
378
379LogicalResult applyGCTDataTaps(const AnnoPathValue &target, DictionaryAttr anno,
380 ApplyState &state);
381
382LogicalResult applyGCTMemTaps(const AnnoPathValue &target, DictionaryAttr anno,
383 ApplyState &state);
384
385LogicalResult applyTraceName(const AnnoPathValue &target, DictionaryAttr anno,
386 ApplyState &state);
387
388LogicalResult applyWiring(const AnnoPathValue &target, DictionaryAttr anno,
389 ApplyState &state);
390
391/// Implements the same behavior as DictionaryAttr::getAs<A> to return the
392/// value of a specific type associated with a key in a dictionary. However,
393/// this is specialized to print a useful error message, specific to custom
394/// processing, on failure.
395template <typename A>
396A tryGetAsBase(DictionaryAttr dict, Attribute root, StringRef key, Location loc,
397 Twine whatSpecific, Twine whatFull, Twine path = Twine()) {
398 SmallString<128> msg;
399 // Check that the key exists.
400 auto value = dict.get(key);
401 if (!value) {
402 if (path.isTriviallyEmpty())
403 (whatSpecific + " did not contain required key '" + key + "'.")
404 .toVector(msg);
405 else
406 (whatSpecific + " with path '" + path +
407 "' did not contain required key '" + key + "'.")
408 .toVector(msg);
409 mlir::emitError(loc, msg).attachNote()
410 << "The full " << whatFull << " is reproduced here: " << root;
411 return nullptr;
412 }
413 // Check that the value has the correct type.
414 auto valueA = dyn_cast<A>(value);
415 if (!valueA) {
416 if (path.isTriviallyEmpty())
417 (whatSpecific + " did not contain the correct type for key '" + key +
418 "'.")
419 .toVector(msg);
420 else
421 (whatSpecific + " with path '" + path +
422 "' did not contain the correct type for key '" + key + "'.")
423 .toVector(msg);
424 mlir::emitError(loc, msg).attachNote()
425 << "The full " << whatFull << " is reproduced here: " << root;
426 return nullptr;
427 }
428 return valueA;
429}
430
431/// Implements the same behavior as DictionaryAttr::getAs<A> to return the
432/// value of a specific type associated with a key in a dictionary. However,
433/// this is specialized to print a useful error message, specific to custom
434/// annotation process, on failure.
435template <typename A>
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 + "'",
439 "Annotation", path);
440}
441
442/// Add ports to the module and all its instances and return the clone for
443/// `instOnPath`. This does not connect the new ports to anything. Replace
444/// the old instances with the new cloned instance in all the caches.
445InstanceOp addPortsToModule(FModuleLike mod, InstanceOp instOnPath,
446 FIRRTLType portType, Direction dir,
447 StringRef newName,
448 InstancePathCache &instancePathcache,
449 CircuitTargetCache *targetCaches = nullptr);
450
451///===----------------------------------------------------------------------===//
452/// LowerAnnotations
453///===----------------------------------------------------------------------===//
454
455/// Annotation resolver and handler.
457 llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr, ApplyState &)>
459 llvm::function_ref<LogicalResult(const AnnoPathValue &, DictionaryAttr,
460 ApplyState &)>
462};
463
464/// Register external annotation records.
465LogicalResult registerAnnotationRecord(
466 StringRef annoClass, AnnoRecord annoRecord,
467 const std::function<void(llvm::Twine)> &errorHandler = {});
468
469///===----------------------------------------------------------------------===//
470/// Standard Utility Resolvers
471///===----------------------------------------------------------------------===//
472
473/// (SFC) FIRRTL SingleTargetAnnotation resolver. Uses the 'target' field of
474/// the annotation with standard parsing to resolve the path. This requires
475/// 'target' to exist and be normalized (per docs/FIRRTLAnnotations.md).
476std::optional<AnnoPathValue> stdResolve(DictionaryAttr anno, ApplyState &state);
477
478/// Resolves with target, if it exists. If not, resolves to the circuit.
479std::optional<AnnoPathValue> tryResolve(DictionaryAttr anno, ApplyState &state);
480
481///===----------------------------------------------------------------------===//
482/// Standard Utility Appliers
483///===----------------------------------------------------------------------===//
484
485/// An applier which puts the annotation on the target and drops the 'target'
486/// field from the annotation. Optionally handles non-local annotations.
487LogicalResult applyWithoutTargetImpl(const AnnoPathValue &target,
488 DictionaryAttr anno, ApplyState &state,
489 bool allowNonLocal);
490
491/// An applier which puts the annotation on the target and drops the 'target'
492/// field from the annotation. Optionally handles non-local annotations.
493/// Ensures the target resolves to an expected type of operation.
494template <bool allowNonLocal, bool allowPortAnnoTarget, typename T,
495 typename... Tr>
496static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
497 DictionaryAttr anno,
498 ApplyState &state) {
499 if (isa<PortAnnoTarget>(target.ref)) {
500 if (!allowPortAnnoTarget)
501 return failure();
502 } else if (!target.isOpOfType<T, Tr...>())
503 return failure();
504
505 return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
506}
507
508template <bool allowNonLocal, typename T, typename... Tr>
509static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
510 DictionaryAttr anno,
511 ApplyState &state) {
512 return applyWithoutTarget<allowNonLocal, false, T, Tr...>(target, anno,
513 state);
514}
515
516/// An applier which puts the annotation on the target and drops the 'target'
517/// field from the annotaiton. Optionally handles non-local annotations.
518template <bool allowNonLocal = false>
519static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
520 DictionaryAttr anno,
521 ApplyState &state) {
522 return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
523}
524
525} // namespace firrtl
526} // namespace circt
527
528#endif // CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
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)
===-------------------------------------------------------------------—===// 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(AnnoTargetCache &&other)
void gatherTargets(FModuleLike mod)
Walk the module and add named things to 'targets'.
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.
FModuleLike getModule() const
Get the parent module of the target.
State threaded through functions for resolving and applying annotations.
DenseSet< InstanceOp > wiringProblemInstRefs
DenseMap< StringAttr, LegacyWiringProblem > legacyWiringProblems
ApplyState(CircuitOp circuit, SymbolTable &symTbl, AddToWorklistFn addToWorklistFn, InstancePathCache &instancePathCache, bool noRefTypePorts)
SmallVector< WiringProblem > wiringProblems
InstancePathCache & instancePathCache
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
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.
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.
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.
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.