CIRCT  19.0.0git
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 
19 #include "circt/Dialect/HW/HWOps.h"
21 #include "llvm/ADT/TypeSwitch.h"
22 
23 namespace circt {
24 namespace firrtl {
25 
26 /// Stores an index into an aggregate.
27 struct TargetToken {
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.
54 struct AnnoPathValue {
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 
76 template <typename T>
77 static 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 
116 template <typename T>
117 static T &operator<<(T &os, const OpAnnoTarget &target) {
118  os << target.getOp()->getAttrOfType<StringAttr>("name").getValue();
119  return os;
120 }
121 
122 template <typename T>
123 static T &operator<<(T &os, const PortAnnoTarget &target) {
124  os << target.getModule().getPortName(target.getPortNo());
125  return os;
126 }
127 
128 template <typename T>
129 static 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 
179 private:
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 
232 private:
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.
239 std::string canonicalizeTarget(StringRef target);
240 
241 /// Parse a FIRRTL annotation path into its constituent parts.
242 std::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.
246 std::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.
252 std::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 private:
323  OpBuilder builder;
324  DenseMap<ArrayAttr, hw::HierPathOp> cache;
325  SymbolTable &symbolTable;
326 };
327 
328 /// State threaded through functions for resolving and applying annotations.
329 struct ApplyState {
330  using AddToWorklistFn = llvm::function_ref<void(DictionaryAttr)>;
331  ApplyState(CircuitOp circuit, SymbolTable &symTbl,
332  AddToWorklistFn addToWorklistFn,
333  InstancePathCache &instancePathCache, bool noRefTypePorts)
334  : circuit(circuit), symTbl(symTbl), addToWorklistFn(addToWorklistFn),
335  instancePathCache(instancePathCache), hierPathCache(circuit, symTbl),
336  noRefTypePorts(noRefTypePorts) {}
337 
338  CircuitOp circuit;
339  SymbolTable &symTbl;
344  size_t numReusedHierPaths = 0;
345 
346  // Options that control annotation lowering.
348 
349  DenseSet<InstanceOp> wiringProblemInstRefs;
350  DenseMap<StringAttr, LegacyWiringProblem> legacyWiringProblems;
351  SmallVector<WiringProblem> wiringProblems;
352 
353  hw::InnerSymbolNamespace &getNamespace(FModuleLike module) {
354  return namespaces[module];
355  }
356 
357  IntegerAttr newID() {
358  return IntegerAttr::get(IntegerType::get(circuit.getContext(), 64),
359  annotationID++);
360  };
361 
362 private:
364  unsigned annotationID = 0;
365 };
366 
367 LogicalResult applyGCTView(const AnnoPathValue &target, DictionaryAttr anno,
368  ApplyState &state);
369 
370 LogicalResult applyGCTDataTaps(const AnnoPathValue &target, DictionaryAttr anno,
371  ApplyState &state);
372 
373 LogicalResult applyGCTMemTaps(const AnnoPathValue &target, DictionaryAttr anno,
374  ApplyState &state);
375 
376 LogicalResult applyOMIR(const AnnoPathValue &target, DictionaryAttr anno,
377  ApplyState &state);
378 
379 LogicalResult applyTraceName(const AnnoPathValue &target, DictionaryAttr anno,
380  ApplyState &state);
381 
382 LogicalResult applyWiring(const AnnoPathValue &target, DictionaryAttr anno,
383  ApplyState &state);
384 
385 /// Implements the same behavior as DictionaryAttr::getAs<A> to return the
386 /// value of a specific type associated with a key in a dictionary. However,
387 /// this is specialized to print a useful error message, specific to custom
388 /// annotation process, on failure.
389 template <typename A>
390 A tryGetAs(DictionaryAttr &dict, const Attribute &root, StringRef key,
391  Location loc, Twine className, Twine path = Twine()) {
392  // Check that the key exists.
393  auto value = dict.get(key);
394  if (!value) {
395  SmallString<128> msg;
396  if (path.isTriviallyEmpty())
397  msg = ("Annotation '" + className + "' did not contain required key '" +
398  key + "'.")
399  .str();
400  else
401  msg = ("Annotation '" + className + "' with path '" + path +
402  "' did not contain required key '" + key + "'.")
403  .str();
404  mlir::emitError(loc, msg).attachNote()
405  << "The full Annotation is reproduced here: " << root << "\n";
406  return nullptr;
407  }
408  // Check that the value has the correct type.
409  auto valueA = dyn_cast_or_null<A>(value);
410  if (!valueA) {
411  SmallString<128> msg;
412  if (path.isTriviallyEmpty())
413  msg = ("Annotation '" + className +
414  "' did not contain the correct type for key '" + key + "'.")
415  .str();
416  else
417  msg = ("Annotation '" + className + "' with path '" + path +
418  "' did not contain the correct type for key '" + key + "'.")
419  .str();
420  mlir::emitError(loc, msg).attachNote()
421  << "The full Annotation is reproduced here: " << root << "\n";
422  return nullptr;
423  }
424  return valueA;
425 }
426 
427 /// Add ports to the module and all its instances and return the clone for
428 /// `instOnPath`. This does not connect the new ports to anything. Replace
429 /// the old instances with the new cloned instance in all the caches.
430 InstanceOp addPortsToModule(FModuleLike mod, InstanceOp instOnPath,
431  FIRRTLType portType, Direction dir,
432  StringRef newName,
433  InstancePathCache &instancePathcache,
434  CircuitTargetCache *targetCaches = nullptr);
435 
436 ///===----------------------------------------------------------------------===//
437 /// LowerAnnotations
438 ///===----------------------------------------------------------------------===//
439 
440 /// Annotation resolver and handler.
441 struct AnnoRecord {
442  llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr, ApplyState &)>
444  llvm::function_ref<LogicalResult(const AnnoPathValue &, DictionaryAttr,
445  ApplyState &)>
447 };
448 
449 /// Register external annotation records.
450 LogicalResult registerAnnotationRecord(
451  StringRef annoClass, AnnoRecord annoRecord,
452  const std::function<void(llvm::Twine)> &errorHandler = {});
453 
454 ///===----------------------------------------------------------------------===//
455 /// Standard Utility Resolvers
456 ///===----------------------------------------------------------------------===//
457 
458 /// (SFC) FIRRTL SingleTargetAnnotation resolver. Uses the 'target' field of
459 /// the annotation with standard parsing to resolve the path. This requires
460 /// 'target' to exist and be normalized (per docs/FIRRTLAnnotations.md).
461 std::optional<AnnoPathValue> stdResolve(DictionaryAttr anno, ApplyState &state);
462 
463 /// Resolves with target, if it exists. If not, resolves to the circuit.
464 std::optional<AnnoPathValue> tryResolve(DictionaryAttr anno, ApplyState &state);
465 
466 ///===----------------------------------------------------------------------===//
467 /// Standard Utility Appliers
468 ///===----------------------------------------------------------------------===//
469 
470 /// An applier which puts the annotation on the target and drops the 'target'
471 /// field from the annotation. Optionally handles non-local annotations.
472 LogicalResult applyWithoutTargetImpl(const AnnoPathValue &target,
473  DictionaryAttr anno, ApplyState &state,
474  bool allowNonLocal);
475 
476 /// An applier which puts the annotation on the target and drops the 'target'
477 /// field from the annotation. Optionally handles non-local annotations.
478 /// Ensures the target resolves to an expected type of operation.
479 template <bool allowNonLocal, bool allowPortAnnoTarget, typename T,
480  typename... Tr>
481 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
482  DictionaryAttr anno,
483  ApplyState &state) {
484  if (isa<PortAnnoTarget>(target.ref)) {
485  if (!allowPortAnnoTarget)
486  return failure();
487  } else if (!target.isOpOfType<T, Tr...>())
488  return failure();
489 
490  return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
491 }
492 
493 template <bool allowNonLocal, typename T, typename... Tr>
494 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
495  DictionaryAttr anno,
496  ApplyState &state) {
497  return applyWithoutTarget<allowNonLocal, false, T, Tr...>(target, anno,
498  state);
499 }
500 
501 /// An applier which puts the annotation on the target and drops the 'target'
502 /// field from the annotaiton. Optionally handles non-local annotations.
503 template <bool allowNonLocal = false>
504 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
505  DictionaryAttr anno,
506  ApplyState &state) {
507  return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
508 }
509 
510 } // namespace firrtl
511 } // namespace circt
512 
513 #endif // CIRCT_DIALECT_FIRRTL_FIRRTLANNOTATIONHELPER_H
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
Definition: FIRRTLTypes.h:518
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: FIRRTLTypes.h:528
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
Direction
The direction of a Component or Cell port.
Definition: CalyxOps.h:72
LogicalResult applyOMIR(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Main entry point to handle scattering of an OMIRAnnotation.
Definition: EmitOMIR.cpp:490
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)
Definition: FIRParser.h:115
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.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
SmallVector< InstanceOp > instances
AnnoPathValue(const SmallVectorImpl< InstanceOp > &insts, AnnoTarget b, unsigned fieldIdx)
===-------------------------------------------------------------------—===// 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(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.
Operation * getOp() const
FModuleLike getModule() const
Get the parent module of the target.
State threaded through functions for resolving and applying annotations.
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
InstancePathCache & instancePathCache
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)
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.