CIRCT  20.0.0git
NLATable.h
Go to the documentation of this file.
1 //===- NLATable.h - Non-Local Anchor Table----------------------*- 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 defines the FIRRTL NLATable.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef CIRCT_DIALECT_FIRRTL_NLATABLE_H
13 #define CIRCT_DIALECT_FIRRTL_NLATABLE_H
14 
16 #include "circt/Dialect/HW/HWOps.h"
17 #include "circt/Support/LLVM.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SetOperations.h"
20 #include "llvm/ADT/iterator.h"
21 
22 namespace circt {
23 namespace firrtl {
24 
25 /// This table tracks nlas and what modules participate in them.
26 ///
27 /// To use this class, retrieve a cached copy from the analysis manager:
28 /// auto &nlaTable = getAnalysis<NLATable>(getOperation());
29 class NLATable {
30 
31 public:
32  /// Create a new NLA table of a circuit. This must be called on a FIRRTL
33  /// CircuitOp or MLIR ModuleOp. To ensure that the analysis does not return
34  /// stale data while a pass is running, it should be kept up-to-date when
35  /// modules are added or renamed and NLAs are updated.
36  explicit NLATable(Operation *operation);
37 
38  /// Lookup all NLAs an operation participates in. This returns a reference to
39  /// the internal record, so make a copy before making any update to the
40  /// NLATable.
41  ArrayRef<hw::HierPathOp> lookup(Operation *op);
42 
43  /// Lookup all NLAs an operation participates in. This returns a reference to
44  /// the internal record, so make a copy before making any update to the
45  /// NLATable.
46  ArrayRef<hw::HierPathOp> lookup(StringAttr name);
47 
48  /// Resolve a symbol to an NLA.
49  hw::HierPathOp getNLA(StringAttr name);
50 
51  /// Resolve a symbol to a Module.
52  FModuleLike getModule(StringAttr name);
53 
54  /// Compute the NLAs that are common between the two modules, `mod1` and
55  /// `mod2` and insert them into the set `common`.
56  /// The set of NLAs that an instance op participates in is the set of common
57  /// NLAs between the parent module and the instance target. This can be used
58  /// to get the set of NLAs that an InstanceOp participates in, instead of
59  /// recording them on the op in the IR.
60  void commonNLAs(StringAttr mod1, StringAttr mod2,
61  DenseSet<hw::HierPathOp> &common) {
62  auto mod1NLAs = lookup(mod1);
63  auto mod2NLAs = lookup(mod2);
64  common.insert(mod1NLAs.begin(), mod1NLAs.end());
65  DenseSet<hw::HierPathOp> set2(mod2NLAs.begin(), mod2NLAs.end());
66  llvm::set_intersect(common, set2);
67  }
68 
69  /// Get the NLAs that the InstanceOp participates in, insert it to the
70  /// DenseSet `nlas`.
71  void getInstanceNLAs(InstanceOp inst, DenseSet<hw::HierPathOp> &nlas) {
72  auto instSym = getInnerSymName(inst);
73  // If there is no inner sym on the InstanceOp, then it does not participate
74  // in any NLA.
75  if (!instSym)
76  return;
77  auto mod = inst->getParentOfType<FModuleOp>().getNameAttr();
78  // Get the NLAs that are common between the parent module and the target
79  // module. This should contain the NLAs that this InstanceOp participates
80  // in.
81  commonNLAs(inst->getParentOfType<FModuleOp>().getNameAttr(),
82  inst.getModuleNameAttr().getAttr(), nlas);
83  // Handle the case when there are more than one Instances for the same
84  // target module. Getting the `commonNLA`, in that case is not enough,
85  // remove the NLAs that donot have the InstanceOp as the innerSym.
86  for (auto nla : llvm::make_early_inc_range(nlas)) {
87  if (!nla.hasInnerSym(mod, instSym))
88  nlas.erase(nla);
89  }
90  }
91 
92  /// Get the NLAs that the module `modName` particiaptes in, and insert them
93  /// into the DenseSet `nlas`.
94  void getNLAsInModule(StringAttr modName, DenseSet<hw::HierPathOp> &nlas) {
95  for (auto nla : lookup(modName))
96  nlas.insert(nla);
97  }
98 
99  //===-------------------------------------------------------------------------
100  // Methods to keep an NLATable up to date.
101  //
102  // These methods are not thread safe. Make sure that modifications are
103  // properly synchronized or performed in a serial context. When the
104  // NLATable is used as an analysis, this is only safe when the pass is
105  // on a CircuitOp.
106 
107  /// Insert a new NLA. This updates two internal records,
108  /// 1. Update the map for the `nlaOp` name to the Operation.
109  /// 2. For each module in the NLA namepath, insert the NLA into the list of
110  /// hwHierPathOps that participate in the corresponding module. This does
111  /// not update the module name to module op map, if any potentially new module
112  /// in the namepath does not already exist in the record.
113  void addNLA(hw::HierPathOp nla);
114 
115  /// Remove the NLA from the analysis. This updates two internal records,
116  /// 1. Remove the NLA name to the operation map entry.
117  /// 2. For each module in the namepath of the NLA, remove the entry from the
118  /// list of NLAs that the module participates in.
119  /// Note that this invalidates any reference to the NLA list returned by
120  /// 'lookup'.
121  void erase(hw::HierPathOp nlaOp, SymbolTable *symbolTable = nullptr);
122 
123  /// Record a new FModuleLike operation. This updates the Module name to Module
124  /// operation map.
125  void addModule(FModuleLike mod) { symToOp[mod.getModuleNameAttr()] = mod; }
126 
127  /// Stop tracking a module. Remove the module from two internal records,
128  /// 1. Module name to Module op map.
129  /// 2. Module name to list of NLAs that the module participates in.
130  void eraseModule(StringAttr name) {
131  symToOp.erase(name);
132  nodeMap.erase(name);
133  }
134 
135  /// Replace the module `oldModule` with `newModule` in the namepath of the nla
136  /// `nlaName`. This moves the nla from the list of `oldModule` to `newModule`.
137  /// Move `nlaName` from the list of NLAs that `oldModule` participates in to
138  /// `newModule`. This can delete and invalidate any reference returned by
139  /// `lookup`.
140  void updateModuleInNLA(StringAttr nlaName, StringAttr oldModule,
141  StringAttr newModule);
142 
143  /// Replace the module `oldModule` with `newModule` in the namepath of the nla
144  /// `nlaOp`. This moves the nla from the list of `oldModule` to `newModule`.
145  /// Move `nlaOp` from the list of NLAs that `oldModule` participates in to
146  /// `newModule`. This can delete and invalidate any reference returned by
147  /// `lookup`.
148  void updateModuleInNLA(hw::HierPathOp nlaOp, StringAttr oldModule,
149  StringAttr newModule);
150 
151  /// Rename a module, this updates the name to module tracking and the name to
152  /// NLA tracking. This moves all the NLAs that `oldModName` is participating
153  /// in to the `newModName`. The `oldModName` must exist in the name to module
154  /// record. This also removes all the entries for `oldModName`.
155  void renameModule(StringAttr oldModName, StringAttr newModName);
156 
157  /// Replace the module `oldModName` with `newModName` in the namepath of any
158  /// NLA. Since the module is being updated, the symbols inside the module
159  /// should also be renamed. Use the rename map `innerSymRenameMap` to update
160  /// the inner_sym names in the namepath.
162  StringAttr newModName, StringAttr oldModName,
163  const DenseMap<StringAttr, StringAttr> &innerSymRenameMap);
164 
165  /// Remove the NLA from the Module. This updates the module name to NLA
166  /// tracking.
167  void removeNLAfromModule(hw::HierPathOp nla, StringAttr mod) {
168  llvm::erase(nodeMap[mod], nla);
169  }
170 
171  /// Remove all the nlas in the set `nlas` from the module. This updates the
172  /// module name to NLA tracking.
173  void removeNLAsfromModule(const DenseSet<hw::HierPathOp> &nlas,
174  StringAttr mod) {
175  llvm::erase_if(nodeMap[mod],
176  [&nlas](const auto &nla) { return nlas.count(nla); });
177  }
178 
179  /// Add the nla to the module. This ensures that the list of NLAs that the
180  /// module participates in is updated. This will be required if `mod` is added
181  /// to the namepath of `nla`.
182  void addNLAtoModule(hw::HierPathOp nla, StringAttr mod) {
183  nodeMap[mod].push_back(nla);
184  }
185 
186 private:
187  NLATable(const NLATable &) = delete;
188 
189  /// Map modules to the NLA's that target them.
190  llvm::DenseMap<StringAttr, SmallVector<hw::HierPathOp, 4>> nodeMap;
191 
192  /// Map symbol names to module and NLA operations.
193  llvm::DenseMap<StringAttr, Operation *> symToOp;
194 };
195 
196 } // namespace firrtl
197 } // namespace circt
198 #endif // CIRCT_DIALECT_FIRRTL_NLATABLE_H
This table tracks nlas and what modules participate in them.
Definition: NLATable.h:29
ArrayRef< hw::HierPathOp > lookup(Operation *op)
Lookup all NLAs an operation participates in.
Definition: NLATable.cpp:41
NLATable(const NLATable &)=delete
void updateModuleInNLA(StringAttr nlaName, StringAttr oldModule, StringAttr newModule)
Replace the module oldModule with newModule in the namepath of the nla nlaName.
Definition: NLATable.cpp:92
void removeNLAsfromModule(const DenseSet< hw::HierPathOp > &nlas, StringAttr mod)
Remove all the nlas in the set nlas from the module.
Definition: NLATable.h:173
llvm::DenseMap< StringAttr, SmallVector< hw::HierPathOp, 4 > > nodeMap
Map modules to the NLA's that target them.
Definition: NLATable.h:190
void renameModule(StringAttr oldModName, StringAttr newModName)
Rename a module, this updates the name to module tracking and the name to NLA tracking.
Definition: NLATable.cpp:100
void addNLA(hw::HierPathOp nla)
Insert a new NLA.
Definition: NLATable.cpp:58
void removeNLAfromModule(hw::HierPathOp nla, StringAttr mod)
Remove the NLA from the Module.
Definition: NLATable.h:167
void addNLAtoModule(hw::HierPathOp nla, StringAttr mod)
Add the nla to the module.
Definition: NLATable.h:182
void eraseModule(StringAttr name)
Stop tracking a module.
Definition: NLATable.h:130
void renameModuleAndInnerRef(StringAttr newModName, StringAttr oldModName, const DenseMap< StringAttr, StringAttr > &innerSymRenameMap)
Replace the module oldModName with newModName in the namepath of any NLA.
Definition: NLATable.cpp:115
void commonNLAs(StringAttr mod1, StringAttr mod2, DenseSet< hw::HierPathOp > &common)
Compute the NLAs that are common between the two modules, mod1 and mod2 and insert them into the set ...
Definition: NLATable.h:60
void erase(hw::HierPathOp nlaOp, SymbolTable *symbolTable=nullptr)
Remove the NLA from the analysis.
Definition: NLATable.cpp:68
void getNLAsInModule(StringAttr modName, DenseSet< hw::HierPathOp > &nlas)
Get the NLAs that the module modName particiaptes in, and insert them into the DenseSet nlas.
Definition: NLATable.h:94
void addModule(FModuleLike mod)
Record a new FModuleLike operation.
Definition: NLATable.h:125
NLATable(Operation *operation)
Create a new NLA table of a circuit.
Definition: NLATable.cpp:17
void getInstanceNLAs(InstanceOp inst, DenseSet< hw::HierPathOp > &nlas)
Get the NLAs that the InstanceOp participates in, insert it to the DenseSet nlas.
Definition: NLATable.h:71
hw::HierPathOp getNLA(StringAttr name)
Resolve a symbol to an NLA.
Definition: NLATable.cpp:48
llvm::DenseMap< StringAttr, Operation * > symToOp
Map symbol names to module and NLA operations.
Definition: NLATable.h:193
FModuleLike getModule(StringAttr name)
Resolve a symbol to a Module.
Definition: NLATable.cpp:53
StringAttr getInnerSymName(Operation *op)
Return the StringAttr for the inner_sym name, if it exists.
Definition: FIRRTLOps.h:108
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21