CIRCT  18.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 = ref.dyn_cast<OpAnnoTarget>())
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 = target.dyn_cast<OpAnnoTarget>())
131  os << op;
132  else if (auto port = target.dyn_cast<PortAnnoTarget>())
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 (target.ref.isa<PortAnnoTarget>()) {
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
lowerAnnotationsNoRefTypePorts FirtoolPreserveValuesMode value
Definition: Firtool.cpp:95
This class implements the same functionality as TypeSwitch except that it uses firrtl::type_dyn_cast ...
Definition: FIRRTLTypes.h:515
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: FIRRTLTypes.h:525
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:53
Direction
The direction of a Component or Cell port.
Definition: CalyxOps.h:65
LogicalResult applyOMIR(const AnnoPathValue &target, DictionaryAttr anno, ApplyState &state)
Main entry point to handle scattering of an OMIRAnnotation.
Definition: EmitOMIR.cpp:489
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.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
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.