14#include "mlir/IR/Builders.h"
15#include "mlir/IR/DialectImplementation.h"
25LogicalResult SequenceOp::verifyRegions() {
26 if (TypeRange(getSequenceType().getElementTypes()) !=
27 getBody()->getArgumentTypes())
28 return emitOpError(
"sequence type does not match block argument types");
33ParseResult SequenceOp::parse(OpAsmParser &parser, OperationState &result) {
35 if (parser.parseSymbolName(
36 result.getOrAddProperties<SequenceOp::Properties>().sym_name))
40 SmallVector<OpAsmParser::Argument> arguments;
41 if (parser.parseArgumentList(arguments, OpAsmParser::Delimiter::Paren,
45 SmallVector<Type> argTypes;
46 SmallVector<Location> argLocs;
47 argTypes.reserve(arguments.size());
48 argLocs.reserve(arguments.size());
49 for (
auto &arg : arguments) {
50 argTypes.push_back(arg.type);
51 argLocs.push_back(arg.sourceLoc ? *arg.sourceLoc : result.location);
53 Type type = SequenceType::get(result.getContext(), argTypes);
54 result.getOrAddProperties<SequenceOp::Properties>().sequenceType =
57 auto loc = parser.getCurrentLocation();
58 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
60 if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
61 return parser.emitError(loc)
62 <<
"'" << result.name.getStringRef() <<
"' op ";
66 std::unique_ptr<Region> bodyRegionRegion = std::make_unique<Region>();
67 if (parser.parseRegion(*bodyRegionRegion, arguments))
70 if (bodyRegionRegion->empty()) {
71 bodyRegionRegion->emplaceBlock();
72 bodyRegionRegion->addArguments(argTypes, argLocs);
74 result.addRegion(std::move(bodyRegionRegion));
79void SequenceOp::print(OpAsmPrinter &p) {
81 p.printSymbolName(getSymNameAttr().getValue());
83 llvm::interleaveComma(getBody()->getArguments(), p,
84 [&](
auto arg) { p.printRegionArgument(arg); });
86 p.printOptionalAttrDictWithKeyword(
87 (*this)->getAttrs(), {getSymNameAttrName(), getSequenceTypeAttrName()});
89 p.printRegion(getBodyRegion(),
false);
97GetSequenceOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
99 symbolTable.lookupNearestSymbolFrom<SequenceOp>(*
this, getSequenceAttr());
102 <<
"'" << getSequence()
103 <<
"' does not reference a valid 'rtg.sequence' operation";
105 if (
seq.getSequenceType() != getType())
106 return emitOpError(
"referenced 'rtg.sequence' op's type does not match");
115LogicalResult SubstituteSequenceOp::verify() {
116 if (getReplacements().
empty())
117 return emitOpError(
"must at least have one replacement value");
119 if (getReplacements().size() >
120 getSequence().getType().getElementTypes().size())
122 "must not have more replacement values than sequence arguments");
124 if (getReplacements().getTypes() !=
125 getSequence().getType().getElementTypes().take_front(
126 getReplacements().size()))
127 return emitOpError(
"replacement types must match the same number of "
128 "sequence argument types from the front");
133LogicalResult SubstituteSequenceOp::inferReturnTypes(
134 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
135 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
136 SmallVectorImpl<Type> &inferredReturnTypes) {
137 ArrayRef<Type> argTypes =
138 cast<SequenceType>(operands[0].getType()).getElementTypes();
140 SequenceType::get(context, argTypes.drop_front(operands.size() - 1));
141 inferredReturnTypes.push_back(seqType);
145ParseResult SubstituteSequenceOp::parse(::mlir::OpAsmParser &parser,
146 ::mlir::OperationState &result) {
147 OpAsmParser::UnresolvedOperand sequenceRawOperand;
148 SmallVector<OpAsmParser::UnresolvedOperand, 4> replacementsOperands;
149 Type sequenceRawType;
151 if (parser.parseOperand(sequenceRawOperand) || parser.parseLParen())
154 auto replacementsOperandsLoc = parser.getCurrentLocation();
155 if (parser.parseOperandList(replacementsOperands) || parser.parseRParen() ||
156 parser.parseColon() || parser.parseType(sequenceRawType) ||
157 parser.parseOptionalAttrDict(result.attributes))
160 if (!isa<SequenceType>(sequenceRawType))
161 return parser.emitError(parser.getNameLoc())
162 <<
"'sequence' must be handle to a sequence or sequence family, but "
166 if (parser.resolveOperand(sequenceRawOperand, sequenceRawType,
170 if (parser.resolveOperands(replacementsOperands,
171 cast<SequenceType>(sequenceRawType)
173 .take_front(replacementsOperands.size()),
174 replacementsOperandsLoc, result.operands))
177 SmallVector<Type> inferredReturnTypes;
178 if (failed(inferReturnTypes(
179 parser.getContext(), result.location, result.operands,
180 result.attributes.getDictionary(parser.getContext()),
181 result.getRawProperties(), result.regions, inferredReturnTypes)))
184 result.addTypes(inferredReturnTypes);
188void SubstituteSequenceOp::print(OpAsmPrinter &p) {
189 p <<
' ' << getSequence() <<
"(" << getReplacements()
190 <<
") : " << getSequence().getType();
191 p.printOptionalAttrDict((*this)->getAttrs(), {});
198ParseResult SetCreateOp::parse(OpAsmParser &parser, OperationState &result) {
199 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> operands;
202 if (parser.parseOperandList(operands) ||
203 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
204 parser.parseType(elemType))
207 result.addTypes({SetType::get(result.getContext(), elemType)});
209 for (
auto operand : operands)
210 if (parser.resolveOperand(operand, elemType, result.operands))
216void SetCreateOp::print(OpAsmPrinter &p) {
218 p.printOperands(getElements());
219 p.printOptionalAttrDict((*this)->getAttrs());
220 p <<
" : " << getSet().getType().getElementType();
223LogicalResult SetCreateOp::verify() {
224 if (getElements().size() > 0) {
227 if (getElements()[0].getType() != getSet().getType().getElementType())
228 return emitOpError() <<
"operand types must match set element type";
238ParseResult BagCreateOp::parse(OpAsmParser &parser, OperationState &result) {
239 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 16> elementOperands,
243 if (!parser.parseOptionalLParen()) {
245 OpAsmParser::UnresolvedOperand elementOperand, multipleOperand;
246 if (parser.parseOperand(multipleOperand) || parser.parseKeyword(
"x") ||
247 parser.parseOperand(elementOperand))
250 elementOperands.push_back(elementOperand);
251 multipleOperands.push_back(multipleOperand);
253 if (parser.parseOptionalComma()) {
254 if (parser.parseRParen())
261 if (parser.parseColon() || parser.parseType(elemType) ||
262 parser.parseOptionalAttrDict(result.attributes))
265 result.addTypes({BagType::get(result.getContext(), elemType)});
267 for (
auto operand : elementOperands)
268 if (parser.resolveOperand(operand, elemType, result.operands))
271 for (
auto operand : multipleOperands)
272 if (parser.resolveOperand(operand, IndexType::
get(result.getContext()),
279void BagCreateOp::print(OpAsmPrinter &p) {
281 if (!getElements().
empty())
283 llvm::interleaveComma(llvm::zip(getElements(), getMultiples()), p,
284 [&](
auto elAndMultiple) {
285 auto [el, multiple] = elAndMultiple;
286 p << multiple <<
" x " << el;
288 if (!getElements().
empty())
291 p <<
" : " << getBag().getType().getElementType();
292 p.printOptionalAttrDict((*this)->getAttrs());
295LogicalResult BagCreateOp::verify() {
296 if (!llvm::all_equal(getElements().getTypes()))
297 return emitOpError() <<
"types of all elements must match";
299 if (getElements().size() > 0)
300 if (getElements()[0].getType() != getBag().getType().getElementType())
301 return emitOpError() <<
"operand types must match bag element type";
310LogicalResult FixedRegisterOp::inferReturnTypes(
311 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
312 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
313 SmallVectorImpl<Type> &inferredReturnTypes) {
314 inferredReturnTypes.push_back(
315 properties.as<Properties *>()->getReg().getType());
319OpFoldResult FixedRegisterOp::fold(FoldAdaptor adaptor) {
return getRegAttr(); }
325LogicalResult VirtualRegisterOp::verify() {
326 if (getAllowedRegs().
empty())
327 return emitOpError(
"must have at least one allowed register");
329 if (llvm::any_of(getAllowedRegs(), [](Attribute attr) {
330 return !isa<RegisterAttrInterface>(attr);
332 return emitOpError(
"all elements must be of RegisterAttrInterface");
334 if (!llvm::all_equal(
335 llvm::map_range(getAllowedRegs().getAsRange<RegisterAttrInterface>(),
336 [](
auto attr) {
return attr.getType(); })))
337 return emitOpError(
"all allowed registers must be of the same type");
342LogicalResult VirtualRegisterOp::inferReturnTypes(
343 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
344 DictionaryAttr attributes, OpaqueProperties properties, RegionRange regions,
345 SmallVectorImpl<Type> &inferredReturnTypes) {
346 auto allowedRegs = properties.as<Properties *>()->getAllowedRegs();
347 if (allowedRegs.empty()) {
349 return mlir::emitError(*loc,
"must have at least one allowed register");
354 auto regAttr = dyn_cast<RegisterAttrInterface>(allowedRegs[0]);
357 return mlir::emitError(
358 *loc,
"allowed register attributes must be of RegisterAttrInterface");
362 inferredReturnTypes.push_back(regAttr.getType());
370LogicalResult TestOp::verifyRegions() {
371 if (!getTarget().entryTypesMatch(getBody()->getArgumentTypes()))
372 return emitOpError(
"argument types must match dict entry types");
381LogicalResult TargetOp::verifyRegions() {
382 if (!getTarget().entryTypesMatch(
383 getBody()->getTerminator()->getOperandTypes()))
384 return emitOpError(
"terminator operand types must match dict entry types");
393#define GET_OP_CLASSES
394#include "circt/Dialect/RTG/IR/RTG.cpp.inc"
static InstancePath empty
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.