CIRCT  19.0.0git
MooreOps.cpp
Go to the documentation of this file.
1 //===- MooreOps.cpp - Implement the Moore operations ----------------------===//
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 implements the Moore dialect operations.
10 //
11 //===----------------------------------------------------------------------===//
12 
15 #include "mlir/IR/Builders.h"
16 
17 using namespace circt;
18 using namespace circt::moore;
19 
20 //===----------------------------------------------------------------------===//
21 // InstanceOp
22 //===----------------------------------------------------------------------===//
23 
24 LogicalResult InstanceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
25  auto *module =
26  symbolTable.lookupNearestSymbolFrom(*this, getModuleNameAttr());
27  if (module == nullptr)
28  return emitError("unknown symbol name '") << getModuleName() << "'";
29 
30  // It must be some sort of module.
31  if (!isa<SVModuleOp>(module))
32  return emitError("symbol '")
33  << getModuleName()
34  << "' must reference a 'moore.module', but got a '"
35  << module->getName() << "' instead";
36 
37  return success();
38 }
39 
40 //===----------------------------------------------------------------------===//
41 // VariableOp
42 //===----------------------------------------------------------------------===//
43 
45  setNameFn(getResult(), getName());
46 }
47 
48 //===----------------------------------------------------------------------===//
49 // NetOp
50 //===----------------------------------------------------------------------===//
51 
53  setNameFn(getResult(), getName());
54 }
55 
56 //===----------------------------------------------------------------------===//
57 // ConstantOp
58 //===----------------------------------------------------------------------===//
59 
60 void ConstantOp::print(OpAsmPrinter &p) {
61  p << " ";
62  p.printAttributeWithoutType(getValueAttr());
63  p.printOptionalAttrDict((*this)->getAttrs(), /*elidedAttrs=*/{"value"});
64  p << " : ";
65  p.printType(getType());
66 }
67 
68 ParseResult ConstantOp::parse(OpAsmParser &parser, OperationState &result) {
69  // Parse the constant value without bit width.
70  APInt value;
71  auto valueLoc = parser.getCurrentLocation();
72 
73  if (parser.parseInteger(value) ||
74  parser.parseOptionalAttrDict(result.attributes) || parser.parseColon())
75  return failure();
76 
77  // Parse the result type.
78  IntType type;
79  if (parser.parseType(type))
80  return failure();
81 
82  // Extend or truncate the constant value to match the size of the type.
83  if (type.getWidth() > value.getBitWidth()) {
84  // sext is always safe here, even for unsigned values, because the
85  // parseOptionalInteger method will return something with a zero in the
86  // top bits if it is a positive number.
87  value = value.sext(type.getWidth());
88  } else if (type.getWidth() < value.getBitWidth()) {
89  // The parser can return an unnecessarily wide result with leading
90  // zeros. This isn't a problem, but truncating off bits is bad.
91  unsigned neededBits =
92  value.isNegative() ? value.getSignificantBits() : value.getActiveBits();
93  if (type.getWidth() < neededBits)
94  return parser.emitError(valueLoc,
95  "constant out of range for result type ")
96  << type;
97  value = value.trunc(type.getWidth());
98  }
99 
100  // Build the attribute and op.
101  auto attrType = IntegerType::get(parser.getContext(), type.getWidth());
102  auto attrValue = IntegerAttr::get(attrType, value);
103 
104  result.addAttribute("value", attrValue);
105  result.addTypes(type);
106  return success();
107 }
108 
109 LogicalResult ConstantOp::verify() {
110  auto attrWidth = getValue().getBitWidth();
111  auto typeWidth = getType().getWidth();
112  if (attrWidth != typeWidth)
113  return emitError("attribute width ")
114  << attrWidth << " does not match return type's width " << typeWidth;
115  return success();
116 }
117 
118 void ConstantOp::build(OpBuilder &builder, OperationState &result, IntType type,
119  const APInt &value) {
120  assert(type.getWidth() == value.getBitWidth() &&
121  "APInt width must match type width");
122  build(builder, result, type,
123  builder.getIntegerAttr(builder.getIntegerType(type.getWidth()), value));
124 }
125 
126 /// This builder allows construction of small signed integers like 0, 1, -1
127 /// matching a specified MLIR type. This shouldn't be used for general constant
128 /// folding because it only works with values that can be expressed in an
129 /// `int64_t`.
130 void ConstantOp::build(OpBuilder &builder, OperationState &result, IntType type,
131  int64_t value) {
132  build(builder, result, type,
133  APInt(type.getWidth(), (uint64_t)value, /*isSigned=*/true));
134 }
135 
136 //===----------------------------------------------------------------------===//
137 // ConcatOp
138 //===----------------------------------------------------------------------===//
139 
140 LogicalResult ConcatOp::inferReturnTypes(
141  MLIRContext *context, std::optional<Location> loc, ValueRange operands,
142  DictionaryAttr attrs, mlir::OpaqueProperties properties,
143  mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
144  Domain domain = Domain::TwoValued;
145  unsigned width = 0;
146  for (auto operand : operands) {
147  auto type = cast<IntType>(operand.getType());
148  if (type.getDomain() == Domain::FourValued)
149  domain = Domain::FourValued;
150  width += type.getWidth();
151  }
152  results.push_back(IntType::get(context, width, domain));
153  return success();
154 }
155 
156 //===----------------------------------------------------------------------===//
157 // ConversionOp
158 //===----------------------------------------------------------------------===//
159 
160 OpFoldResult ConversionOp::fold(FoldAdaptor adaptor) {
161  // Fold away no-op casts.
162  if (getInput().getType() == getResult().getType())
163  return getInput();
164  return {};
165 }
166 
167 //===----------------------------------------------------------------------===//
168 // BoolCastOp
169 //===----------------------------------------------------------------------===//
170 
171 OpFoldResult BoolCastOp::fold(FoldAdaptor adaptor) {
172  // Fold away no-op casts.
173  if (getInput().getType() == getResult().getType())
174  return getInput();
175  return {};
176 }
177 
178 //===----------------------------------------------------------------------===//
179 // TableGen generated logic.
180 //===----------------------------------------------------------------------===//
181 
182 // Provide the autogenerated implementation guts for the Op classes.
183 #define GET_OP_CLASSES
184 #include "circt/Dialect/Moore/Moore.cpp.inc"
185 #include "circt/Dialect/Moore/MooreEnums.cpp.inc"
assert(baseType &&"element must be base type")
int32_t width
Definition: FIRRTL.cpp:36
Builder builder
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
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)
StringAttr getName(ArrayAttr names, size_t idx)
Return the name at the specified index of the ArrayAttr or null if it cannot be determined.
void getAsmResultNames(OpAsmSetValueNameFn setNameFn, StringRef instanceName, ArrayAttr resultNames, ValueRange results)
Suggest a name for each result value based on the saved result names attribute.
Domain
The number of values each bit of a type can assume.
Definition: MooreTypes.h:27
@ FourValued
Four-valued types such as logic or integer.
@ TwoValued
Two-valued types such as bit or int.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
Definition: LLVM.h:186