CIRCT 20.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 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
53raw_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());
63 }
64
65 explicit ModulePortInfo(ArrayRef<PortInfo> mergedPorts)
66 : ports(mergedPorts.begin(), mergedPorts.end()) {
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 ||
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 ||
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
173private:
174 // convert input inout<type> -> inout type
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
198public:
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)
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
231private:
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")
OS & operator<<(OS &os, const InnerSymTarget &target)
Printing InnerSymTarget's.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
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
PortInfo & atInput(size_t idx)
PortInfo & atOutput(size_t idx)
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
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.
const PortInfo & atInput(size_t idx) const
ConstPortDirectionRange getOutputs() const
SmallVector< PortInfo >::const_iterator const_iterator
SmallVector< PortInfo >::iterator iterator
const_iterator begin() const
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: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