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 =
value.getType().dyn_cast<IntegerType>();
28 assert(valueType && destTy.isa<IntegerType>() &&
29 valueType.getWidth() <= destTy.getIntOrFloatBitWidth() &&
30 valueType.getWidth() != 0 &&
"invalid sext operands");
32 if (valueType == destTy)
38 auto signBits =
builder.createOrFold<ReplicateOp>(
39 loc, signBit, destTy.getIntOrFloatBitWidth() - valueType.getWidth());
44 ImplicitLocOpBuilder &
builder) {
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();
183 LogicalResult ReplicateOp::verify() {
186 auto srcWidth = getOperand().getType().cast<IntegerType>().
getWidth();
187 auto dstWidth = getType().cast<IntegerType>().
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");
212 LogicalResult AddOp::verify() {
return verifyUTBinOp(*
this); }
214 LogicalResult MulOp::verify() {
return verifyUTBinOp(*
this); }
216 LogicalResult AndOp::verify() {
return verifyUTBinOp(*
this); }
218 LogicalResult OrOp::verify() {
return verifyUTBinOp(*
this); }
220 LogicalResult XorOp::verify() {
return verifyUTBinOp(*
this); }
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 += input.getType().cast<IntegerType>().
getWidth();
245 LogicalResult ConcatOp::verify() {
246 unsigned tyWidth = getType().cast<IntegerType>().
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 = hd.getType().cast<IntegerType>().
getWidth();
266 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
267 DictionaryAttr attrs, mlir::OpaqueProperties properties,
268 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
278 LogicalResult ExtractOp::verify() {
279 unsigned srcWidth = getInput().getType().cast<IntegerType>().
getWidth();
280 unsigned dstWidth = getType().cast<IntegerType>().
getWidth();
281 if (getLowBit() >= srcWidth || srcWidth - getLowBit() < dstWidth)
282 return emitOpError(
"from bit too large for input"), failure();
287 LogicalResult TruthTableOp::verify() {
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)
llvm::SmallVector< StringAttr > inputs
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.
uint64_t getWidth(Type t)
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)
This file defines an intermediate representation for circuits acting as an abstraction for constraint...