CIRCT 24.0.0git
Loading...
Searching...
No Matches
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
20namespace circt {
21namespace hw {
22
23/// This holds the name, type, direction of a module's ports
24struct 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
38 /// Return a unique numeric identifier for this port.
39 ssize_t getId() const { return isOutput() ? argNum : (-1 - argNum); };
40
41 // Inspect or mutate attributes
42 InnerSymAttr getSym() const;
43 void setSym(InnerSymAttr sym, MLIRContext *ctx);
44
45 // Return the port's Verilog name. This returns either the port's name, or the
46 // `hw.verilogName` attribute if one is present. After `ExportVerilog` has
47 // run, this will reflect the exact name of the port as emitted to the Verilog
48 // output.
49 StringRef getVerilogName() const;
50};
51
52raw_ostream &operator<<(raw_ostream &printer, PortInfo port);
53
54/// This holds a decoded list of input/inout and output ports for a module or
55/// instance.
57 explicit ModulePortInfo(ArrayRef<PortInfo> inputs,
58 ArrayRef<PortInfo> outputs) {
59 ports.insert(ports.end(), inputs.begin(), inputs.end());
60 ports.insert(ports.end(), outputs.begin(), outputs.end());
61 }
62
63 explicit ModulePortInfo(ArrayRef<PortInfo> mergedPorts)
64 : ports(mergedPorts.begin(), mergedPorts.end()) {}
65
66 using iterator = SmallVector<PortInfo>::iterator;
67 using const_iterator = SmallVector<PortInfo>::const_iterator;
68
69 iterator begin() { return ports.begin(); }
70 iterator end() { return ports.end(); }
71 const_iterator begin() const { return ports.begin(); }
72 const_iterator end() const { return ports.end(); }
73
74 using PortDirectionRange = llvm::iterator_range<
75 llvm::filter_iterator<iterator, std::function<bool(const PortInfo &)>>>;
76
77 using ConstPortDirectionRange = llvm::iterator_range<llvm::filter_iterator<
78 const_iterator, std::function<bool(const PortInfo &)>>>;
79
81 std::function<bool(const PortInfo &)> predicateFn;
82 if (input) {
83 predicateFn = [](const PortInfo &port) -> bool {
84 return port.dir == ModulePort::Direction::Input;
85 };
86 } else {
87 predicateFn = [](const PortInfo &port) -> bool {
88 return port.dir == ModulePort::Direction::Output;
89 };
90 }
91 return llvm::make_filter_range(ports, predicateFn);
92 }
93
95 std::function<bool(const PortInfo &)> predicateFn;
96 if (input) {
97 predicateFn = [](const PortInfo &port) -> bool {
98 return port.dir == ModulePort::Direction::Input;
99 };
100 } else {
101 predicateFn = [](const PortInfo &port) -> bool {
102 return port.dir == ModulePort::Direction::Output;
103 };
104 }
105 return llvm::make_filter_range(ports, predicateFn);
106 }
107
109
111
113 return getPortsOfDirection(true);
114 }
115
117 return getPortsOfDirection(false);
118 }
119
120 size_t size() const { return ports.size(); }
121 size_t sizeInputs() const {
122 auto r = getInputs();
123 return std::distance(r.begin(), r.end());
124 }
125 size_t sizeOutputs() const {
126 auto r = getOutputs();
127 return std::distance(r.begin(), r.end());
128 }
129
130 size_t portNumForInput(size_t idx) const {
131 size_t port = 0;
132 while (idx || ports[port].isOutput()) {
133 if (!ports[port].isOutput())
134 --idx;
135 ++port;
136 }
137 return port;
138 }
139
140 size_t portNumForOutput(size_t idx) const {
141 size_t port = 0;
142 while (idx || !ports[port].isOutput()) {
143 if (ports[port].isOutput())
144 --idx;
145 ++port;
146 }
147 return port;
148 }
149
150 PortInfo &at(size_t idx) { return ports[idx]; }
151 PortInfo &atInput(size_t idx) { return ports[portNumForInput(idx)]; }
152 PortInfo &atOutput(size_t idx) { return ports[portNumForOutput(idx)]; }
153
154 const PortInfo &at(size_t idx) const { return ports[idx]; }
155 const PortInfo &atInput(size_t idx) const {
156 return ports[portNumForInput(idx)];
157 }
158 const PortInfo &atOutput(size_t idx) const {
159 return ports[portNumForOutput(idx)];
160 }
161
162 void eraseInput(size_t idx) {
163 assert(idx < sizeInputs());
164 ports.erase(ports.begin() + portNumForInput(idx));
165 }
166
167private:
168 /// This contains a list of all ports. Input first.
169 SmallVector<PortInfo> ports;
170};
171
172// This provides capability for looking up port indices based on port names.
174 FailureOr<unsigned>
175 lookupPortIndex(const llvm::DenseMap<StringAttr, unsigned> &portMap,
176 StringAttr name) const {
177 auto it = portMap.find(name);
178 if (it == portMap.end())
179 return failure();
180 return it->second;
181 }
182
183public:
184 explicit ModulePortLookupInfo(MLIRContext *ctx,
185 const ModulePortInfo &portInfo)
186 : ctx(ctx) {
187 for (auto &in : portInfo.getInputs())
188 inputPortMap[in.name] = in.argNum;
189
190 for (auto &out : portInfo.getOutputs())
191 outputPortMap[out.name] = out.argNum;
192 }
193
194 explicit ModulePortLookupInfo(MLIRContext *ctx,
195 const SmallVector<PortInfo> &portInfo)
197
198 // Return the index of the input port with the specified name.
199 FailureOr<unsigned> getInputPortIndex(StringAttr name) const {
200 return lookupPortIndex(inputPortMap, name);
201 }
202
203 // Return the index of the output port with the specified name.
204 FailureOr<unsigned> getOutputPortIndex(StringAttr name) const {
205 return lookupPortIndex(outputPortMap, name);
206 }
207
208 FailureOr<unsigned> getInputPortIndex(StringRef name) const {
209 return getInputPortIndex(StringAttr::get(ctx, name));
210 }
211
212 FailureOr<unsigned> getOutputPortIndex(StringRef name) const {
213 return getOutputPortIndex(StringAttr::get(ctx, name));
214 }
215
216private:
217 llvm::DenseMap<StringAttr, unsigned> inputPortMap;
218 llvm::DenseMap<StringAttr, unsigned> outputPortMap;
219 MLIRContext *ctx;
220};
221
222} // namespace hw
223} // namespace circt
224
225#endif // CIRCT_DIALECT_HW_PORTIMPLEMENTATION_H
assert(baseType &&"element must be base type")
false return failure()
Parse an optional keyword or string and set instance into 'result'.
OS & operator<<(OS &os, const InnerSymTarget &target)
Printing InnerSymTarget's.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds a decoded list of input/inout and output ports for a module or instance.
const PortInfo & at(size_t idx) const
PortInfo & atInput(size_t idx)
PortInfo & atOutput(size_t idx)
llvm::iterator_range< llvm::filter_iterator< const_iterator, std::function< bool(const PortInfo &)> > > ConstPortDirectionRange
PortInfo & at(size_t idx)
ModulePortInfo(ArrayRef< PortInfo > inputs, ArrayRef< PortInfo > outputs)
const PortInfo & atOutput(size_t idx) const
size_t portNumForInput(size_t idx) const
size_t portNumForOutput(size_t idx) const
ConstPortDirectionRange getPortsOfDirection(bool input) const
SmallVector< PortInfo > ports
This contains a list of all ports. Input first.
const PortInfo & atInput(size_t idx) const
ConstPortDirectionRange getOutputs() const
SmallVector< PortInfo >::const_iterator const_iterator
SmallVector< PortInfo >::iterator iterator
const_iterator begin() const
llvm::iterator_range< llvm::filter_iterator< iterator, std::function< bool(const PortInfo &)> > > PortDirectionRange
const_iterator end() const
ConstPortDirectionRange getInputs() const
PortDirectionRange getPortsOfDirection(bool input)
PortDirectionRange getInputs()
PortDirectionRange getOutputs()
ModulePortInfo(ArrayRef< PortInfo > mergedPorts)
llvm::DenseMap< StringAttr, unsigned > inputPortMap
llvm::DenseMap< StringAttr, unsigned > outputPortMap
FailureOr< unsigned > lookupPortIndex(const llvm::DenseMap< StringAttr, unsigned > &portMap, StringAttr name) const
FailureOr< unsigned > getInputPortIndex(StringAttr name) const
FailureOr< unsigned > getOutputPortIndex(StringRef name) const
FailureOr< unsigned > getInputPortIndex(StringRef name) const
ModulePortLookupInfo(MLIRContext *ctx, const ModulePortInfo &portInfo)
ModulePortLookupInfo(MLIRContext *ctx, const SmallVector< PortInfo > &portInfo)
FailureOr< unsigned > getOutputPortIndex(StringAttr name) const
mlir::StringAttr name
Definition HWTypes.h:33
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