CIRCT  19.0.0git
FIRRTLOps.h
Go to the documentation of this file.
1 //===- FIRRTLOps.h - Declare FIRRTL dialect operations ----------*- 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 operation class for the FIRRTL IR.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef CIRCT_DIALECT_FIRRTL_OPS_H
14 #define CIRCT_DIALECT_FIRRTL_OPS_H
15 
23 #include "circt/Support/FieldRef.h"
25 #include "mlir/IR/Builders.h"
26 #include "mlir/IR/OpImplementation.h"
27 #include "mlir/IR/RegionKindInterface.h"
28 #include "mlir/IR/SymbolTable.h"
29 #include "mlir/Interfaces/FunctionInterfaces.h"
30 #include "mlir/Interfaces/InferTypeOpInterface.h"
31 #include "mlir/Interfaces/SideEffectInterfaces.h"
32 
33 namespace circt {
34 namespace firrtl {
35 
36 class StrictConnectOp;
37 
38 // works for regs, nodes, and wires
39 bool hasDroppableName(Operation *op);
40 
41 /// Return true if the specified operation is a firrtl expression.
42 bool isExpression(Operation *op);
43 
44 /// Return the number of ports in a module-like thing (modules, memories, etc)
45 size_t getNumPorts(Operation *op);
46 
47 /// Return true if the specified operation has a constant value. This trivially
48 /// checks for `firrtl.constant` and friends, but also looks through subaccesses
49 /// and correctly handles wires driven with only constant values.
50 bool isConstant(Operation *op);
51 bool isConstant(Value value);
52 
53 /// Returns true if the value results from an expression with duplex flow.
54 /// Duplex values have special treatment in bundle connect operations, and
55 /// their flip orientation is not used to determine the direction of each
56 /// pairwise connect.
57 bool isDuplexValue(Value val);
58 
59 enum class Flow : uint8_t { None, Source, Sink, Duplex };
60 
61 /// Get a flow's reverse.
62 Flow swapFlow(Flow flow);
63 
64 constexpr bool isValidSrc(Flow flow) {
65  return uint8_t(flow) & uint8_t(Flow::Source);
66 }
67 
68 constexpr bool isValidDst(Flow flow) {
69  return uint8_t(flow) & uint8_t(Flow::Sink);
70 }
71 
72 /// Compute the flow for a Value, \p val, as determined by the FIRRTL
73 /// specification. This recursively walks backwards from \p val to the
74 /// declaration. The resulting flow is a combination of the declaration flow
75 /// (output ports and instance inputs are sinks, registers and wires are
76 /// duplex, anything else is a source) and the number of intermediary flips.
77 /// An even number of flips will result in the same flow as the declaration.
78 /// An odd number of flips will result in reversed flow being returned. The
79 /// reverse of source is sink. The reverse of sink is source. The reverse of
80 /// duplex is duplex. The \p accumulatedFlow parameter sets the initial flow.
81 /// A user should normally \a not have to change this from its default of \p
82 /// Flow::Source.
83 Flow foldFlow(Value val, Flow accumulatedFlow = Flow::Source);
84 
85 enum class DeclKind { Port, Instance, Other };
86 
87 DeclKind getDeclarationKind(Value val);
88 
89 enum class ReadPortSubfield { addr, en, clk, data };
90 enum class WritePortSubfield { addr, en, clk, data, mask };
92 
93 /// Allow 'or'ing MemDirAttr. This allows combining Read and Write into
94 /// ReadWrite.
95 inline MemDirAttr operator|(MemDirAttr lhs, MemDirAttr rhs) {
96  return static_cast<MemDirAttr>(
97  static_cast<std::underlying_type<MemDirAttr>::type>(lhs) |
98  static_cast<std::underlying_type<MemDirAttr>::type>(rhs));
99 }
100 
101 inline MemDirAttr &operator|=(MemDirAttr &lhs, MemDirAttr rhs) {
102  lhs = lhs | rhs;
103  return lhs;
104 }
105 
106 /// Return the StringAttr for the inner_sym name, if it exists.
107 inline StringAttr getInnerSymName(Operation *op) {
108  auto s = op->getAttrOfType<hw::InnerSymAttr>(
110  if (s)
111  return s.getSymName();
112  return StringAttr();
113 }
114 
115 /// Check whether a block argument ("port") or the operation defining a value
116 /// has a `DontTouch` annotation, or a symbol that should prevent certain types
117 /// of canonicalizations.
118 bool hasDontTouch(Value value);
119 
120 /// Check whether an operation has a `DontTouch` annotation, or a symbol that
121 /// should prevent certain types of canonicalizations.
122 bool hasDontTouch(Operation *op);
123 
124 /// Scan all the uses of the specified value, checking to see if there is
125 /// exactly one connect that has the value as its destination. This returns the
126 /// operation if found and if all the other users are "reads" from the value.
127 /// Returns null if there are no connects, or multiple connects to the value, or
128 /// if the value is involved in an `AttachOp`.
129 ///
130 /// Note that this will simply return the connect, which is located *anywhere*
131 /// after the definition of the value. Users of this function are likely
132 /// interested in the source side of the returned connect, the definition of
133 /// which does likely not dominate the original value.
134 StrictConnectOp getSingleConnectUserOf(Value value);
135 
136 // Out-of-line implementation of various trait verification methods and
137 // functions commonly used among operations.
138 namespace impl {
139 LogicalResult verifySameOperandsIntTypeKind(Operation *op);
140 
141 // Type inference adaptor for FIRRTL operations.
142 LogicalResult inferReturnTypes(
143  MLIRContext *context, std::optional<Location> loc, ValueRange operands,
144  DictionaryAttr attrs, mlir::OpaqueProperties properties,
145  mlir::RegionRange regions, SmallVectorImpl<Type> &results,
146  llvm::function_ref<FIRRTLType(ValueRange, ArrayRef<NamedAttribute>,
147  std::optional<Location>)>
148  callback);
149 
150 // Common type inference functions.
152  std::optional<Location> loc);
154  std::optional<Location> loc);
156  std::optional<Location> loc);
158  std::optional<Location> loc);
159 FIRRTLType inferReductionResult(FIRRTLType arg, std::optional<Location> loc);
160 
161 // Common parsed argument validation functions.
162 LogicalResult validateBinaryOpArguments(ValueRange operands,
163  ArrayRef<NamedAttribute> attrs,
164  Location loc);
165 LogicalResult validateUnaryOpArguments(ValueRange operands,
166  ArrayRef<NamedAttribute> attrs,
167  Location loc);
168 LogicalResult validateOneOperandOneConst(ValueRange operands,
169  ArrayRef<NamedAttribute> attrs,
170  Location loc);
171 } // namespace impl
172 
173 /// A binary operation where the operands have the same integer kind.
174 template <typename ConcreteOp>
176  : public OpTrait::TraitBase<ConcreteOp, SameOperandsIntTypeKind> {
177 public:
178  static LogicalResult verifyTrait(Operation *op) {
180  }
181 };
182 
183 // This is a summary of a FIRRTL::MemOp. It defines the relevant properties of
184 // the FIRRTL memory, and can be constructed by parsing its attributes.
185 struct FirMemory {
186  size_t numReadPorts;
189  size_t dataWidth;
190  size_t depth;
191  size_t readLatency;
192  size_t writeLatency;
193  size_t maskBits;
194  seq::RUW readUnderWrite;
195  seq::WUW writeUnderWrite;
196  SmallVector<int32_t> writeClockIDs;
197  StringAttr modName;
198  bool isMasked;
199  MemoryInitAttr init;
200  StringAttr prefix;
201 
202  // Location is carried along but not considered part of the identity of this.
203  Location loc;
204  // Flag to indicate if the memory was under the DUT hierarchy, only used in
205  // LowerToHW. Not part of the identity.
206  bool isInDut = false;
207  // The original MemOp, only used in LowerToHW. Also not part of the identity.
208  Operation *op = nullptr;
209 
210  auto getTuple() const {
211  return std::make_tuple(
214  writeClockIDs, init ? init.getFilename().getValue() : "",
215  init ? init.getIsBinary() : false, init ? init.getIsInline() : false,
216  prefix ? prefix.getValue() : "");
217  }
218  bool operator<(const FirMemory &rhs) const {
219  return getTuple() < rhs.getTuple();
220  }
221  bool operator==(const FirMemory &rhs) const {
222  return getTuple() == rhs.getTuple();
223  }
224  StringAttr getFirMemoryName() const;
225 
226  /**
227  * Check whether the memory is a seq mem.
228  *
229  * The following conditions must hold:
230  * 1. read latency and write latency of one.
231  * 2. undefined read-under-write behavior.
232  */
233  bool isSeqMem() const {
234  if (readLatency != 1 || writeLatency != 1)
235  return false;
236  return dataWidth > 0;
237  }
238 };
239 
240 } // namespace firrtl
241 } // namespace circt
242 
243 #define GET_OP_CLASSES
244 #include "circt/Dialect/FIRRTL/FIRRTL.h.inc"
245 
246 //===----------------------------------------------------------------------===//
247 // Traits
248 //===----------------------------------------------------------------------===//
249 
250 namespace llvm {
251 template <>
252 struct DenseMapInfo<circt::firrtl::FModuleOp> {
253  using Operation = mlir::Operation;
254  using FModuleOp = circt::firrtl::FModuleOp;
255  static inline FModuleOp getEmptyKey() {
256  return FModuleOp::getFromOpaquePointer(
257  DenseMapInfo<Operation *>::getEmptyKey());
258  }
259  static inline FModuleOp getTombstoneKey() {
260  return FModuleOp::getFromOpaquePointer(
261  DenseMapInfo<Operation *>::getTombstoneKey());
262  }
263  static unsigned getHashValue(const FModuleOp &val) {
264  return DenseMapInfo<Operation *>::getHashValue(val);
265  }
266  static bool isEqual(const FModuleOp &lhs, const FModuleOp &rhs) {
267  return lhs == rhs;
268  }
269 };
270 } // end namespace llvm
271 
272 #endif // CIRCT_DIALECT_FIRRTL_OPS_H
A binary operation where the operands have the same integer kind.
Definition: FIRRTLOps.h:176
static LogicalResult verifyTrait(Operation *op)
Definition: FIRRTLOps.h:178
static StringRef getInnerSymbolAttrName()
Return the name of the attribute used for inner symbol names.
LogicalResult validateBinaryOpArguments(ValueRange operands, ArrayRef< NamedAttribute > attrs, Location loc)
Definition: FIRRTLOps.cpp:4829
FIRRTLType inferElementwiseResult(FIRRTLType lhs, FIRRTLType rhs, std::optional< Location > loc)
Definition: FIRRTLOps.cpp:4914
LogicalResult inferReturnTypes(MLIRContext *context, std::optional< Location > loc, ValueRange operands, DictionaryAttr attrs, mlir::OpaqueProperties properties, mlir::RegionRange regions, SmallVectorImpl< Type > &results, llvm::function_ref< FIRRTLType(ValueRange, ArrayRef< NamedAttribute >, std::optional< Location >)> callback)
LogicalResult validateUnaryOpArguments(ValueRange operands, ArrayRef< NamedAttribute > attrs, Location loc)
Definition: FIRRTLOps.cpp:5007
FIRRTLType inferBitwiseResult(FIRRTLType lhs, FIRRTLType rhs, std::optional< Location > loc)
Definition: FIRRTLOps.cpp:4895
FIRRTLType inferAddSubResult(FIRRTLType lhs, FIRRTLType rhs, std::optional< Location > loc)
Definition: FIRRTLOps.cpp:4839
FIRRTLType inferComparisonResult(FIRRTLType lhs, FIRRTLType rhs, std::optional< Location > loc)
Definition: FIRRTLOps.cpp:4936
FIRRTLType inferReductionResult(FIRRTLType arg, std::optional< Location > loc)
Definition: FIRRTLOps.cpp:5100
LogicalResult validateOneOperandOneConst(ValueRange operands, ArrayRef< NamedAttribute > attrs, Location loc)
Definition: FIRRTLOps.cpp:5152
LogicalResult verifySameOperandsIntTypeKind(Operation *op)
Definition: FIRRTLOps.cpp:4819
Flow swapFlow(Flow flow)
Get a flow's reverse.
Definition: FIRRTLOps.cpp:156
bool isConstant(Operation *op)
Return true if the specified operation has a constant value.
Definition: FIRRTLOps.cpp:4494
constexpr bool isValidDst(Flow flow)
Definition: FIRRTLOps.h:68
Flow foldFlow(Value val, Flow accumulatedFlow=Flow::Source)
Compute the flow for a Value, val, as determined by the FIRRTL specification.
Definition: FIRRTLOps.cpp:182
bool hasDontTouch(Value value)
Check whether a block argument ("port") or the operation defining a value has a DontTouch annotation,...
Definition: FIRRTLOps.cpp:287
size_t getNumPorts(Operation *op)
Return the number of ports in a module-like thing (modules, memories, etc)
Definition: FIRRTLOps.cpp:271
bool isDuplexValue(Value val)
Returns true if the value results from an expression with duplex flow.
Definition: FIRRTLOps.cpp:99
bool hasDroppableName(Operation *op)
Return true if the name is droppable.
constexpr bool isValidSrc(Flow flow)
Definition: FIRRTLOps.h:64
MemDirAttr operator|(MemDirAttr lhs, MemDirAttr rhs)
Allow 'or'ing MemDirAttr.
Definition: FIRRTLOps.h:95
bool isExpression(Operation *op)
Return true if the specified operation is a firrtl expression.
Definition: FIRRTLOps.cpp:3865
StrictConnectOp getSingleConnectUserOf(Value value)
Scan all the uses of the specified value, checking to see if there is exactly one connect that has th...
DeclKind getDeclarationKind(Value val)
Definition: FIRRTLOps.cpp:259
StringAttr getInnerSymName(Operation *op)
Return the StringAttr for the inner_sym name, if it exists.
Definition: FIRRTLOps.h:107
MemDirAttr & operator|=(MemDirAttr &lhs, MemDirAttr rhs)
Definition: FIRRTLOps.h:101
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
bool isSeqMem() const
Check whether the memory is a seq mem.
Definition: FIRRTLOps.h:233
bool operator==(const FirMemory &rhs) const
Definition: FIRRTLOps.h:221
MemoryInitAttr init
Definition: FIRRTLOps.h:199
StringAttr getFirMemoryName() const
Definition: FIRRTLOps.cpp:3217
bool operator<(const FirMemory &rhs) const
Definition: FIRRTLOps.h:218
auto getTuple() const
Definition: FIRRTLOps.h:210
SmallVector< int32_t > writeClockIDs
Definition: FIRRTLOps.h:196
static unsigned getHashValue(const FModuleOp &val)
Definition: FIRRTLOps.h:263
static bool isEqual(const FModuleOp &lhs, const FModuleOp &rhs)
Definition: FIRRTLOps.h:266