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