20 #include "mlir/IR/Builders.h"
21 #include "mlir/IR/DialectImplementation.h"
22 #include "mlir/Interfaces/FunctionImplementation.h"
23 #include "mlir/Interfaces/FunctionInterfaces.h"
24 #include "llvm/ADT/BitVector.h"
25 #include "llvm/ADT/SmallPtrSet.h"
26 #include "llvm/ADT/TypeSwitch.h"
28 using namespace circt;
35 static ParseResult
parsePhysLoc(OpAsmParser &p, PhysLocationAttr &attr) {
36 llvm::SMLoc loc = p.getCurrentLocation();
40 if (p.parseKeyword(&devTypeStr) || p.parseKeyword(
"x") || p.parseColon() ||
41 p.parseInteger(x) || p.parseKeyword(
"y") || p.parseColon() ||
42 p.parseInteger(y) || p.parseKeyword(
"n") || p.parseColon() ||
46 std::optional<PrimitiveType> devType = symbolizePrimitiveType(devTypeStr);
48 p.emitError(loc,
"Unknown device type '" + devTypeStr +
"'");
51 PrimitiveTypeAttr devTypeAttr =
57 static void printPhysLoc(OpAsmPrinter &p, Operation *, PhysLocationAttr loc) {
58 p << stringifyPrimitiveType(loc.getPrimitiveType().getValue())
59 <<
" x: " << loc.getX() <<
" y: " << loc.getY() <<
" n: " << loc.getNum();
63 LocationVectorAttr &locs) {
64 SmallVector<PhysLocationAttr, 32> locArr;
66 if (p.parseAttribute(type) || p.parseLSquare() ||
67 p.parseCommaSeparatedList(
68 [&]() { return parseOptionalRegLoc(locArr, p); }) ||
73 [&p]() {
return p.emitError(p.getNameLoc()); }, type, locArr)))
80 LocationVectorAttr locs) {
81 p << locs.getType() <<
" [";
82 llvm::interleaveComma(locs.getLocs(), p, [&p](PhysLocationAttr loc) {
83 printOptionalRegLoc(loc, p);
89 hw::InnerRefAttr &innerRef) {
91 if (p.parseAttribute(sym))
93 auto loc = p.getCurrentLocation();
94 if (sym.getNestedReferences().size() != 1)
95 return p.emitError(loc,
"expected <module sym>::<inner name>");
97 sym.getRootReference(),
98 sym.getNestedReferences().front().getRootReference());
102 hw::InnerRefAttr innerRef) {
103 MLIRContext *
ctxt = innerRef.getContext();
104 StringRef innerRefNameStr, moduleStr;
105 if (innerRef.getName())
106 innerRefNameStr = innerRef.getName().getValue();
107 if (innerRef.getModule())
108 moduleStr = innerRef.getModule().getValue();
117 ArrayAttr DynamicInstanceOp::getPath() {
118 SmallVector<Attribute, 16> path;
121 path.push_back(next.getInstanceRefAttr());
124 std::reverse(path.begin(), path.end());
132 void OutputOp::build(OpBuilder &odsBuilder, OperationState &odsState) {}
142 ParseResult SystolicArrayOp::parse(OpAsmParser &parser,
143 OperationState &result) {
144 uint64_t numRows, numColumns;
145 Type rowType, columnType;
146 OpAsmParser::UnresolvedOperand rowInputs, columnInputs;
147 llvm::SMLoc loc = parser.getCurrentLocation();
148 if (parser.parseLSquare() || parser.parseOperand(rowInputs) ||
149 parser.parseColon() || parser.parseInteger(numRows) ||
150 parser.parseKeyword(
"x") || parser.parseType(rowType) ||
151 parser.parseRSquare() || parser.parseLSquare() ||
152 parser.parseOperand(columnInputs) || parser.parseColon() ||
153 parser.parseInteger(numColumns) || parser.parseKeyword(
"x") ||
154 parser.parseType(columnType) || parser.parseRSquare())
159 SmallVector<Value> operands;
160 if (parser.resolveOperands({rowInputs, columnInputs},
161 {rowInputType, columnInputType}, loc, operands))
163 result.addOperands(operands);
166 SmallVector<OpAsmParser::Argument> peArgs;
167 if (parser.parseKeyword(
"pe")) {
170 llvm::SMLoc peLoc = parser.getCurrentLocation();
171 if (parser.parseArgumentList(peArgs, AsmParser::Delimiter::Paren)) {
174 if (peArgs.size() != 2) {
175 return parser.emitError(peLoc,
"expected two operands");
178 peArgs[0].type = rowType;
179 peArgs[1].type = columnType;
181 if (parser.parseArrow() || parser.parseLParen() ||
182 parser.parseType(peOutputType) || parser.parseRParen())
188 Region *pe = result.addRegion();
190 peLoc = parser.getCurrentLocation();
192 if (parser.parseRegion(*pe, peArgs))
195 if (pe->getBlocks().size() != 1)
196 return parser.emitError(peLoc,
"expected one block for the PE");
197 Operation *peTerm = pe->getBlocks().front().getTerminator();
198 if (peTerm->getOperands().size() != 1)
199 return peTerm->emitOpError(
"expected one return value");
200 if (peTerm->getOperand(0).getType() != peOutputType)
201 return peTerm->emitOpError(
"expected return type as given in parent: ")
207 void SystolicArrayOp::print(OpAsmPrinter &p) {
208 hw::ArrayType rowInputType = cast<hw::ArrayType>(getRowInputs().getType());
209 hw::ArrayType columnInputType = cast<hw::ArrayType>(getColInputs().getType());
211 p.printOperand(getRowInputs());
212 p <<
" : " << rowInputType.getNumElements() <<
" x ";
213 p.printType(rowInputType.getElementType());
215 p.printOperand(getColInputs());
216 p <<
" : " << columnInputType.getNumElements() <<
" x ";
217 p.printType(columnInputType.getElementType());
220 p.printOperand(getPe().getArgument(0));
222 p.printOperand(getPe().getArgument(1));
226 cast<hw::ArrayType>(getPeOutputs().getType()).getElementType())
229 p.printRegion(getPe(),
false);
239 if (!isa<hw::HWDialect, comb::CombDialect, msft::MSFTDialect>(
241 return emitOpError() <<
"expected only hw, comb, and msft dialect ops "
242 "inside the datapath.";
252 Operation *PDMulticycleOp::getTopModule(hw::HWSymbolCache &cache) {
257 if (srcTop != dstTop) {
258 emitOpError(
"source and destination paths must refer to the same top-level "
265 #define GET_OP_CLASSES
266 #include "circt/Dialect/MSFT/MSFT.cpp.inc"
static void printListOptionalRegLocList(OpAsmPrinter &p, Operation *, LocationVectorAttr locs)
static ParseResult parseListOptionalRegLocList(OpAsmParser &p, LocationVectorAttr &locs)
static void printPhysLoc(OpAsmPrinter &p, Operation *, PhysLocationAttr loc)
static ParseResult parseImplicitInnerRef(OpAsmParser &p, hw::InnerRefAttr &innerRef)
void printImplicitInnerRef(OpAsmPrinter &p, Operation *, hw::InnerRefAttr innerRef)
static ParseResult parsePhysLoc(OpAsmParser &p, PhysLocationAttr &attr)
static Block * getBodyBlock(FModuleLike mod)
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.
Operation * getHierPathTopModule(Location loc, circt::hw::HWSymbolCache &symCache, FlatSymbolRefAttr pathSym)
Returns the top-level module which the given HierPathOp that defines pathSym, refers to.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.