15 #include "mlir/IR/Builders.h"
16 #include "mlir/IR/ImplicitLocOpBuilder.h"
17 #include "mlir/IR/PatternMatch.h"
18 #include "llvm/Support/FormatVariadic.h"
20 using namespace circt;
27 IntegerType valueType = dyn_cast<IntegerType>(value.getType());
28 assert(valueType && isa<IntegerType>(destTy) &&
29 valueType.getWidth() <= destTy.getIntOrFloatBitWidth() &&
30 valueType.getWidth() != 0 &&
"invalid sext operands");
32 if (valueType == destTy)
37 builder.createOrFold<
ExtractOp>(loc, value, valueType.getWidth() - 1, 1);
38 auto signBits = builder.createOrFold<ReplicateOp>(
39 loc, signBit, destTy.getIntOrFloatBitWidth() - valueType.getWidth());
40 return builder.createOrFold<
ConcatOp>(loc, signBits, value);
44 ImplicitLocOpBuilder &builder) {
50 auto allOnes = builder.create<
hw::ConstantOp>(loc, value.getType(), -1);
51 return builder.createOrFold<
XorOp>(loc, value, allOnes, twoState);
63 ICmpPredicate ICmpOp::getFlippedPredicate(ICmpPredicate predicate) {
65 case ICmpPredicate::eq:
66 return ICmpPredicate::eq;
67 case ICmpPredicate::ne:
68 return ICmpPredicate::ne;
69 case ICmpPredicate::slt:
70 return ICmpPredicate::sgt;
71 case ICmpPredicate::sle:
72 return ICmpPredicate::sge;
73 case ICmpPredicate::sgt:
74 return ICmpPredicate::slt;
75 case ICmpPredicate::sge:
76 return ICmpPredicate::sle;
77 case ICmpPredicate::ult:
78 return ICmpPredicate::ugt;
79 case ICmpPredicate::ule:
80 return ICmpPredicate::uge;
81 case ICmpPredicate::ugt:
82 return ICmpPredicate::ult;
83 case ICmpPredicate::uge:
84 return ICmpPredicate::ule;
85 case ICmpPredicate::ceq:
86 return ICmpPredicate::ceq;
87 case ICmpPredicate::cne:
88 return ICmpPredicate::cne;
89 case ICmpPredicate::weq:
90 return ICmpPredicate::weq;
91 case ICmpPredicate::wne:
92 return ICmpPredicate::wne;
94 llvm_unreachable(
"unknown comparison predicate");
97 bool ICmpOp::isPredicateSigned(ICmpPredicate predicate) {
99 case ICmpPredicate::ult:
100 case ICmpPredicate::ugt:
101 case ICmpPredicate::ule:
102 case ICmpPredicate::uge:
103 case ICmpPredicate::ne:
104 case ICmpPredicate::eq:
105 case ICmpPredicate::cne:
106 case ICmpPredicate::ceq:
107 case ICmpPredicate::wne:
108 case ICmpPredicate::weq:
110 case ICmpPredicate::slt:
111 case ICmpPredicate::sgt:
112 case ICmpPredicate::sle:
113 case ICmpPredicate::sge:
116 llvm_unreachable(
"unknown comparison predicate");
121 ICmpPredicate ICmpOp::getNegatedPredicate(ICmpPredicate predicate) {
123 case ICmpPredicate::eq:
124 return ICmpPredicate::ne;
125 case ICmpPredicate::ne:
126 return ICmpPredicate::eq;
127 case ICmpPredicate::slt:
128 return ICmpPredicate::sge;
129 case ICmpPredicate::sle:
130 return ICmpPredicate::sgt;
131 case ICmpPredicate::sgt:
132 return ICmpPredicate::sle;
133 case ICmpPredicate::sge:
134 return ICmpPredicate::slt;
135 case ICmpPredicate::ult:
136 return ICmpPredicate::uge;
137 case ICmpPredicate::ule:
138 return ICmpPredicate::ugt;
139 case ICmpPredicate::ugt:
140 return ICmpPredicate::ule;
141 case ICmpPredicate::uge:
142 return ICmpPredicate::ult;
143 case ICmpPredicate::ceq:
144 return ICmpPredicate::cne;
145 case ICmpPredicate::cne:
146 return ICmpPredicate::ceq;
147 case ICmpPredicate::weq:
148 return ICmpPredicate::wne;
149 case ICmpPredicate::wne:
150 return ICmpPredicate::weq;
152 llvm_unreachable(
"unknown comparison predicate");
157 bool ICmpOp::isEqualAllOnes() {
158 if (getPredicate() != ICmpPredicate::eq)
162 dyn_cast_or_null<hw::ConstantOp>(getOperand(1).getDefiningOp()))
163 return op1.getValue().isAllOnes();
169 bool ICmpOp::isNotEqualZero() {
170 if (getPredicate() != ICmpPredicate::ne)
174 dyn_cast_or_null<hw::ConstantOp>(getOperand(1).getDefiningOp()))
175 return op1.getValue().isZero();
186 auto srcWidth = cast<IntegerType>(getOperand().getType()).getWidth();
187 auto dstWidth = cast<IntegerType>(getType()).getWidth();
189 return emitOpError(
"replicate does not take zero bit integer");
191 if (srcWidth > dstWidth)
192 return emitOpError(
"replicate cannot shrink bitwidth of operand"),
195 if (dstWidth % srcWidth)
196 return emitOpError(
"replicate must produce integer multiple of operand"),
207 if (op->getOperands().empty())
208 return op->emitOpError(
"requires 1 or more args");
224 bool XorOp::isBinaryNot() {
225 if (getNumOperands() != 2)
227 if (
auto cst = getOperand(1).getDefiningOp<hw::ConstantOp>())
228 if (cst.getValue().isAllOnes())
238 unsigned resultWidth = 0;
239 for (
auto input : inputs) {
240 resultWidth += hw::type_cast<IntegerType>(input.getType()).getWidth();
246 unsigned tyWidth = cast<IntegerType>(getType()).getWidth();
248 if (tyWidth != operandsTotalWidth)
249 return emitOpError(
"ConcatOp requires operands total width to "
250 "match type width. operands "
252 << operandsTotalWidth <<
", but concatOp type width is " << tyWidth;
257 void ConcatOp::build(OpBuilder &builder, OperationState &result, Value hd,
259 result.addOperands(ValueRange{hd});
260 result.addOperands(tl);
261 unsigned hdWidth = cast<IntegerType>(hd.getType()).getWidth();
262 result.addTypes(builder.getIntegerType(
getTotalWidth(tl) + hdWidth));
265 LogicalResult ConcatOp::inferReturnTypes(
266 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
267 DictionaryAttr attrs, mlir::OpaqueProperties properties,
268 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
279 unsigned srcWidth = cast<IntegerType>(getInput().getType()).getWidth();
280 unsigned dstWidth = cast<IntegerType>(getType()).getWidth();
281 if (getLowBit() >= srcWidth || srcWidth - getLowBit() < dstWidth)
282 return emitOpError(
"from bit too large for input"), failure();
288 size_t numInputs = getInputs().size();
289 if (numInputs >=
sizeof(
size_t) * 8)
290 return emitOpError(
"Truth tables support a maximum of ")
291 <<
sizeof(size_t) * 8 - 1 <<
" inputs on your platform";
293 ArrayAttr table = getLookupTable();
294 if (table.size() != (1ull << numInputs))
295 return emitOpError(
"Expected lookup table of 2^n length");
304 #define GET_OP_CLASSES
305 #include "circt/Dialect/Comb/Comb.cpp.inc"
assert(baseType &&"element must be base type")
static unsigned getTotalWidth(ValueRange inputs)
static LogicalResult verifyUTBinOp(Operation *op)
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Value createOrFoldNot(Location loc, Value value, OpBuilder &builder, bool twoState=false)
Create a `‘Not’' gate on a value.
Value createOrFoldSExt(Location loc, Value value, Type destTy, OpBuilder &builder)
Create a sign extension operation from a value of integer type to an equal or larger integer type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.