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