CIRCT  20.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  const SymbolTable &getSymbolTable() const { return symbolTable; }
323 
324 private:
325  OpBuilder builder;
326  DenseMap<ArrayAttr, hw::HierPathOp> cache;
327  SymbolTable &symbolTable;
328 };
329 
330 /// State threaded through functions for resolving and applying annotations.
331 struct ApplyState {
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 
355  hw::InnerSymbolNamespace &getNamespace(FModuleLike module) {
356  return namespaces[module];
357  }
358 
359  IntegerAttr newID() {
360  return IntegerAttr::get(IntegerType::get(circuit.getContext(), 64),
361  annotationID++);
362  };
363 
364 private:
366  unsigned annotationID = 0;
367 };
368 
369 LogicalResult applyGCTView(const AnnoPathValue &target, DictionaryAttr anno,
370  ApplyState &state);
371 
372 LogicalResult applyGCTDataTaps(const AnnoPathValue &target, DictionaryAttr anno,
373  ApplyState &state);
374 
375 LogicalResult applyGCTMemTaps(const AnnoPathValue &target, DictionaryAttr anno,
376  ApplyState &state);
377 
378 LogicalResult applyOMIR(const AnnoPathValue &target, DictionaryAttr anno,
379  ApplyState &state);
380 
381 LogicalResult applyTraceName(const AnnoPathValue &target, DictionaryAttr anno,
382  ApplyState &state);
383 
384 LogicalResult applyWiring(const AnnoPathValue &target, DictionaryAttr anno,
385  ApplyState &state);
386 
387 /// Implements the same behavior as DictionaryAttr::getAs<A> to return the
388 /// value of a specific type associated with a key in a dictionary. However,
389 /// this is specialized to print a useful error message, specific to custom
390 /// annotation process, on failure.
391 template <typename A>
392 A tryGetAs(DictionaryAttr &dict, const Attribute &root, StringRef key,
393  Location loc, Twine className, Twine path = Twine()) {
394  // Check that the key exists.
395  auto value = dict.get(key);
396  if (!value) {
397  SmallString<128> msg;
398  if (path.isTriviallyEmpty())
399  msg = ("Annotation '" + className + "' did not contain required key '" +
400  key + "'.")
401  .str();
402  else
403  msg = ("Annotation '" + className + "' with path '" + path +
404  "' did not contain required key '" + key + "'.")
405  .str();
406  mlir::emitError(loc, msg).attachNote()
407  << "The full Annotation is reproduced here: " << root << "\n";
408  return nullptr;
409  }
410  // Check that the value has the correct type.
411  auto valueA = dyn_cast_or_null<A>(value);
412  if (!valueA) {
413  SmallString<128> msg;
414  if (path.isTriviallyEmpty())
415  msg = ("Annotation '" + className +
416  "' did not contain the correct type for key '" + key + "'.")
417  .str();
418  else
419  msg = ("Annotation '" + className + "' with path '" + path +
420  "' did not contain the correct type for key '" + key + "'.")
421  .str();
422  mlir::emitError(loc, msg).attachNote()
423  << "The full Annotation is reproduced here: " << root << "\n";
424  return nullptr;
425  }
426  return valueA;
427 }
428 
429 /// Add ports to the module and all its instances and return the clone for
430 /// `instOnPath`. This does not connect the new ports to anything. Replace
431 /// the old instances with the new cloned instance in all the caches.
432 InstanceOp addPortsToModule(FModuleLike mod, InstanceOp instOnPath,
433  FIRRTLType portType, Direction dir,
434  StringRef newName,
435  InstancePathCache &instancePathcache,
436  CircuitTargetCache *targetCaches = nullptr);
437 
438 ///===----------------------------------------------------------------------===//
439 /// LowerAnnotations
440 ///===----------------------------------------------------------------------===//
441 
442 /// Annotation resolver and handler.
443 struct AnnoRecord {
444  llvm::function_ref<std::optional<AnnoPathValue>(DictionaryAttr, ApplyState &)>
446  llvm::function_ref<LogicalResult(const AnnoPathValue &, DictionaryAttr,
447  ApplyState &)>
449 };
450 
451 /// Register external annotation records.
452 LogicalResult registerAnnotationRecord(
453  StringRef annoClass, AnnoRecord annoRecord,
454  const std::function<void(llvm::Twine)> &errorHandler = {});
455 
456 ///===----------------------------------------------------------------------===//
457 /// Standard Utility Resolvers
458 ///===----------------------------------------------------------------------===//
459 
460 /// (SFC) FIRRTL SingleTargetAnnotation resolver. Uses the 'target' field of
461 /// the annotation with standard parsing to resolve the path. This requires
462 /// 'target' to exist and be normalized (per docs/FIRRTLAnnotations.md).
463 std::optional<AnnoPathValue> stdResolve(DictionaryAttr anno, ApplyState &state);
464 
465 /// Resolves with target, if it exists. If not, resolves to the circuit.
466 std::optional<AnnoPathValue> tryResolve(DictionaryAttr anno, ApplyState &state);
467 
468 ///===----------------------------------------------------------------------===//
469 /// Standard Utility Appliers
470 ///===----------------------------------------------------------------------===//
471 
472 /// An applier which puts the annotation on the target and drops the 'target'
473 /// field from the annotation. Optionally handles non-local annotations.
474 LogicalResult applyWithoutTargetImpl(const AnnoPathValue &target,
475  DictionaryAttr anno, ApplyState &state,
476  bool allowNonLocal);
477 
478 /// An applier which puts the annotation on the target and drops the 'target'
479 /// field from the annotation. Optionally handles non-local annotations.
480 /// Ensures the target resolves to an expected type of operation.
481 template <bool allowNonLocal, bool allowPortAnnoTarget, typename T,
482  typename... Tr>
483 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
484  DictionaryAttr anno,
485  ApplyState &state) {
486  if (isa<PortAnnoTarget>(target.ref)) {
487  if (!allowPortAnnoTarget)
488  return failure();
489  } else if (!target.isOpOfType<T, Tr...>())
490  return failure();
491 
492  return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
493 }
494 
495 template <bool allowNonLocal, typename T, typename... Tr>
496 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
497  DictionaryAttr anno,
498  ApplyState &state) {
499  return applyWithoutTarget<allowNonLocal, false, T, Tr...>(target, anno,
500  state);
501 }
502 
503 /// An applier which puts the annotation on the target and drops the 'target'
504 /// field from the annotaiton. Optionally handles non-local annotations.
505 template <bool allowNonLocal = false>
506 static LogicalResult applyWithoutTarget(const AnnoPathValue &target,
507  DictionaryAttr anno,
508  ApplyState &state) {
509  return applyWithoutTargetImpl(target, anno, state, allowNonLocal);
510 }
511 
512 } // namespace firrtl
513 } // namespace circt
514 
515 #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:520
FIRRTLTypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: FIRRTLTypes.h:530
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
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:498
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.
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...
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const InstanceInfo::LatticeValue &value)
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)
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.