CIRCT  20.0.0git
PortImplementation.h
Go to the documentation of this file.
1 //===- PortImplementation.h - Declare HW op interfaces ----------*- 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 the port structure of HW modules and instances.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef CIRCT_DIALECT_HW_PORTIMPLEMENTATION_H
14 #define CIRCT_DIALECT_HW_PORTIMPLEMENTATION_H
15 
18 #include "circt/Support/LLVM.h"
19 
20 namespace circt {
21 namespace hw {
22 
23 /// This holds the name, type, direction of a module's ports
24 struct PortInfo : public ModulePort {
25  /// This is the argument index or the result index depending on the direction.
26  /// "0" for an output means the first output, "0" for a in/inout means the
27  /// first argument.
28  size_t argNum = ~0U;
29 
30  /// The optional symbol for this port.
31  DictionaryAttr attrs = {};
32  LocationAttr loc = {};
33 
34  StringRef getName() const { return name.getValue(); }
35  bool isInput() const { return dir == ModulePort::Direction::Input; }
36  bool isOutput() const { return dir == ModulePort::Direction::Output; }
37  bool isInOut() const { return dir == ModulePort::Direction::InOut; }
38 
39  /// Return a unique numeric identifier for this port.
40  ssize_t getId() const { return isOutput() ? argNum : (-1 - argNum); };
41 
42  // Inspect or mutate attributes
43  InnerSymAttr getSym() const;
44  void setSym(InnerSymAttr sym, MLIRContext *ctx);
45 
46  // Return the port's Verilog name. This returns either the port's name, or the
47  // `hw.verilogName` attribute if one is present. After `ExportVerilog` has
48  // run, this will reflect the exact name of the port as emitted to the Verilog
49  // output.
50  StringRef getVerilogName() const;
51 };
52 
53 raw_ostream &operator<<(raw_ostream &printer, PortInfo port);
54 
55 /// This holds a decoded list of input/inout and output ports for a module or
56 /// instance.
58  explicit ModulePortInfo(ArrayRef<PortInfo> inputs,
59  ArrayRef<PortInfo> outputs) {
60  ports.insert(ports.end(), inputs.begin(), inputs.end());
61  ports.insert(ports.end(), outputs.begin(), outputs.end());
62  sanitizeInOut();
63  }
64 
65  explicit ModulePortInfo(ArrayRef<PortInfo> mergedPorts)
66  : ports(mergedPorts.begin(), mergedPorts.end()) {
67  sanitizeInOut();
68  }
69 
70  using iterator = SmallVector<PortInfo>::iterator;
71  using const_iterator = SmallVector<PortInfo>::const_iterator;
72 
73  iterator begin() { return ports.begin(); }
74  iterator end() { return ports.end(); }
75  const_iterator begin() const { return ports.begin(); }
76  const_iterator end() const { return ports.end(); }
77 
78  using PortDirectionRange = llvm::iterator_range<
79  llvm::filter_iterator<iterator, std::function<bool(const PortInfo &)>>>;
80 
81  using ConstPortDirectionRange = llvm::iterator_range<llvm::filter_iterator<
82  const_iterator, std::function<bool(const PortInfo &)>>>;
83 
85  std::function<bool(const PortInfo &)> predicateFn;
86  if (input) {
87  predicateFn = [](const PortInfo &port) -> bool {
88  return port.dir == ModulePort::Direction::Input ||
89  port.dir == ModulePort::Direction::InOut;
90  };
91  } else {
92  predicateFn = [](const PortInfo &port) -> bool {
93  return port.dir == ModulePort::Direction::Output;
94  };
95  }
96  return llvm::make_filter_range(ports, predicateFn);
97  }
98 
100  std::function<bool(const PortInfo &)> predicateFn;
101  if (input) {
102  predicateFn = [](const PortInfo &port) -> bool {
103  return port.dir == ModulePort::Direction::Input ||
104  port.dir == ModulePort::Direction::InOut;
105  };
106  } else {
107  predicateFn = [](const PortInfo &port) -> bool {
108  return port.dir == ModulePort::Direction::Output;
109  };
110  }
111  return llvm::make_filter_range(ports, predicateFn);
112  }
113 
115 
117 
119  return getPortsOfDirection(true);
120  }
121 
123  return getPortsOfDirection(false);
124  }
125 
126  size_t size() const { return ports.size(); }
127  size_t sizeInputs() const {
128  auto r = getInputs();
129  return std::distance(r.begin(), r.end());
130  }
131  size_t sizeOutputs() const {
132  auto r = getOutputs();
133  return std::distance(r.begin(), r.end());
134  }
135 
136  size_t portNumForInput(size_t idx) const {
137  size_t port = 0;
138  while (idx || ports[port].isOutput()) {
139  if (!ports[port].isOutput())
140  --idx;
141  ++port;
142  }
143  return port;
144  }
145 
146  size_t portNumForOutput(size_t idx) const {
147  size_t port = 0;
148  while (idx || !ports[port].isOutput()) {
149  if (ports[port].isOutput())
150  --idx;
151  ++port;
152  }
153  return port;
154  }
155 
156  PortInfo &at(size_t idx) { return ports[idx]; }
157  PortInfo &atInput(size_t idx) { return ports[portNumForInput(idx)]; }
158  PortInfo &atOutput(size_t idx) { return ports[portNumForOutput(idx)]; }
159 
160  const PortInfo &at(size_t idx) const { return ports[idx]; }
161  const PortInfo &atInput(size_t idx) const {
162  return ports[portNumForInput(idx)];
163  }
164  const PortInfo &atOutput(size_t idx) const {
165  return ports[portNumForOutput(idx)];
166  }
167 
168  void eraseInput(size_t idx) {
169  assert(idx < sizeInputs());
170  ports.erase(ports.begin() + portNumForInput(idx));
171  }
172 
173 private:
174  // convert input inout<type> -> inout type
175  void sanitizeInOut() {
176  for (auto &p : ports)
177  if (auto inout = dyn_cast<hw::InOutType>(p.type)) {
178  p.type = inout.getElementType();
180  }
181  }
182 
183  /// This contains a list of all ports. Input first.
184  SmallVector<PortInfo> ports;
185 };
186 
187 // This provides capability for looking up port indices based on port names.
189  FailureOr<unsigned>
190  lookupPortIndex(const llvm::DenseMap<StringAttr, unsigned> &portMap,
191  StringAttr name) const {
192  auto it = portMap.find(name);
193  if (it == portMap.end())
194  return failure();
195  return it->second;
196  }
197 
198 public:
199  explicit ModulePortLookupInfo(MLIRContext *ctx,
200  const ModulePortInfo &portInfo)
201  : ctx(ctx) {
202  for (auto &in : portInfo.getInputs())
203  inputPortMap[in.name] = in.argNum;
204 
205  for (auto &out : portInfo.getOutputs())
206  outputPortMap[out.name] = out.argNum;
207  }
208 
209  explicit ModulePortLookupInfo(MLIRContext *ctx,
210  const SmallVector<PortInfo> &portInfo)
211  : ModulePortLookupInfo(ctx, ModulePortInfo(portInfo)) {}
212 
213  // Return the index of the input port with the specified name.
214  FailureOr<unsigned> getInputPortIndex(StringAttr name) const {
215  return lookupPortIndex(inputPortMap, name);
216  }
217 
218  // Return the index of the output port with the specified name.
219  FailureOr<unsigned> getOutputPortIndex(StringAttr name) const {
220  return lookupPortIndex(outputPortMap, name);
221  }
222 
223  FailureOr<unsigned> getInputPortIndex(StringRef name) const {
224  return getInputPortIndex(StringAttr::get(ctx, name));
225  }
226 
227  FailureOr<unsigned> getOutputPortIndex(StringRef name) const {
228  return getOutputPortIndex(StringAttr::get(ctx, name));
229  }
230 
231 private:
232  llvm::DenseMap<StringAttr, unsigned> inputPortMap;
233  llvm::DenseMap<StringAttr, unsigned> outputPortMap;
234  MLIRContext *ctx;
235 };
236 
237 } // namespace hw
238 } // namespace circt
239 
240 #endif // CIRCT_DIALECT_HW_PORTIMPLEMENTATION_H
assert(baseType &&"element must be base type")
@ Input
Definition: HW.h:35
@ Output
Definition: HW.h:35
@ InOut
Definition: HW.h:35
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:55
OS & operator<<(OS &os, const InnerSymTarget &target)
Printing InnerSymTarget's.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Definition: hw.py:1
This holds a decoded list of input/inout and output ports for a module or instance.
const PortInfo & at(size_t idx) const
const PortInfo & atInput(size_t idx) const
ModulePortInfo(ArrayRef< PortInfo > inputs, ArrayRef< PortInfo > outputs)
size_t portNumForInput(size_t idx) const
llvm::iterator_range< llvm::filter_iterator< iterator, std::function< bool(const PortInfo &)> >> PortDirectionRange
size_t portNumForOutput(size_t idx) const
ConstPortDirectionRange getPortsOfDirection(bool input) const
llvm::iterator_range< llvm::filter_iterator< const_iterator, std::function< bool(const PortInfo &)> >> ConstPortDirectionRange
SmallVector< PortInfo > ports
This contains a list of all ports. Input first.
PortInfo & at(size_t idx)
ConstPortDirectionRange getOutputs() const
SmallVector< PortInfo >::const_iterator const_iterator
const PortInfo & atOutput(size_t idx) const
SmallVector< PortInfo >::iterator iterator
const_iterator begin() const
PortInfo & atInput(size_t idx)
const_iterator end() const
ConstPortDirectionRange getInputs() const
PortDirectionRange getPortsOfDirection(bool input)
PortInfo & atOutput(size_t idx)
PortDirectionRange getInputs()
PortDirectionRange getOutputs()
ModulePortInfo(ArrayRef< PortInfo > mergedPorts)
llvm::DenseMap< StringAttr, unsigned > inputPortMap
llvm::DenseMap< StringAttr, unsigned > outputPortMap
FailureOr< unsigned > getOutputPortIndex(StringRef name) const
FailureOr< unsigned > getInputPortIndex(StringAttr name) const
FailureOr< unsigned > lookupPortIndex(const llvm::DenseMap< StringAttr, unsigned > &portMap, StringAttr name) const
ModulePortLookupInfo(MLIRContext *ctx, const ModulePortInfo &portInfo)
FailureOr< unsigned > getInputPortIndex(StringRef name) const
ModulePortLookupInfo(MLIRContext *ctx, const SmallVector< PortInfo > &portInfo)
FailureOr< unsigned > getOutputPortIndex(StringAttr name) const
mlir::StringAttr name
Definition: HWTypes.h:30
This holds the name, type, direction of a module's ports.
StringRef getVerilogName() const
ssize_t getId() const
Return a unique numeric identifier for this port.
StringRef getName() const
DictionaryAttr attrs
The optional symbol for this port.
size_t argNum
This is the argument index or the result index depending on the direction.
void setSym(InnerSymAttr sym, MLIRContext *ctx)
InnerSymAttr getSym() const