16 #include "mlir/Dialect/Func/IR/FuncOps.h"
17 #include "mlir/IR/PatternMatch.h"
18 #include "mlir/Interfaces/FunctionImplementation.h"
19 #include "llvm/ADT/MapVector.h"
22 using namespace circt;
25 ParseResult DPIFuncOp::parse(OpAsmParser &parser, OperationState &result) {
26 auto builder = parser.getBuilder();
28 (void)mlir::impl::parseOptionalVisibilityKeyword(parser, result.attributes);
32 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
36 SmallVector<hw::module_like_impl::PortParse> ports;
42 result.addAttribute(DPIFuncOp::getModuleTypeAttrName(result.name), modType);
46 auto unknownLoc = builder.getUnknownLoc();
47 SmallVector<Attribute> attrs, locs;
48 auto nonEmptyLocsFn = [unknownLoc](Attribute attr) {
49 return attr && cast<Location>(attr) != unknownLoc;
52 for (
auto &port : ports) {
53 attrs.push_back(port.attrs ? port.attrs : builder.getDictionaryAttr({}));
54 locs.push_back(port.sourceLoc ? Location(*port.sourceLoc) : unknownLoc);
57 result.addAttribute(DPIFuncOp::getPerArgumentAttrsAttrName(result.name),
58 builder.getArrayAttr(attrs));
61 if (llvm::any_of(locs, nonEmptyLocsFn))
62 result.addAttribute(DPIFuncOp::getArgumentLocsAttrName(result.name),
63 builder.getArrayAttr(locs));
66 if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
73 sim::DPICallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
75 symbolTable.lookupNearestSymbolFrom(*
this, getCalleeAttr());
77 return emitError(
"cannot find function declaration '")
78 << getCallee() <<
"'";
79 if (isa<func::FuncOp, sim::DPIFuncOp>(referencedOp))
81 return emitError(
"callee must be 'sim.dpi.func' or 'func.func' but got '")
82 << referencedOp->getName() <<
"'";
85 void DPIFuncOp::print(OpAsmPrinter &p) {
89 op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
93 StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
94 if (
auto visibility = op->getAttrOfType<StringAttr>(visibilityAttrName))
95 p << visibility.getValue() <<
' ';
96 p.printSymbolName(funcName);
98 p, op->getRegion(0), op.getModuleType(),
99 getPerArgumentAttrsAttr()
100 ? ArrayRef<Attribute>(getPerArgumentAttrsAttr().getValue())
101 : ArrayRef<Attribute>{},
102 getArgumentLocs() ? SmallVector<Location>(
103 getArgumentLocs().value().getAsRange<Location>())
104 : ArrayRef<Location>{});
106 mlir::function_interface_impl::printFunctionAttributes(
108 {visibilityAttrName, getModuleTypeAttrName(),
109 getPerArgumentAttrsAttrName(), getArgumentLocsAttrName()});
112 OpFoldResult FormatLitOp::fold(FoldAdaptor adaptor) {
return getLiteralAttr(); }
114 OpFoldResult FormatDecOp::fold(FoldAdaptor adaptor) {
118 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
119 SmallVector<char, 16> strBuf;
120 intAttr.getValue().toString(strBuf, 10U, getIsSigned());
122 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
123 unsigned padWidth = FormatDecOp::getDecimalWidth(
width, getIsSigned());
124 padWidth = padWidth > strBuf.size() ? padWidth - strBuf.size() : 0;
126 SmallVector<char, 8> padding(padWidth,
' ');
132 OpFoldResult FormatHexOp::fold(FoldAdaptor adaptor) {
136 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
137 SmallVector<char, 8> strBuf;
138 intAttr.getValue().toString(strBuf, 16U,
false,
142 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
143 unsigned padWidth =
width / 4;
146 padWidth = padWidth > strBuf.size() ? padWidth - strBuf.size() : 0;
148 SmallVector<char, 8> padding(padWidth,
'0');
154 OpFoldResult FormatBinOp::fold(FoldAdaptor adaptor) {
158 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
159 SmallVector<char, 32> strBuf;
160 intAttr.getValue().toString(strBuf, 2U,
false);
162 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
163 unsigned padWidth =
width > strBuf.size() ?
width - strBuf.size() : 0;
165 SmallVector<char, 32> padding(padWidth,
'0');
171 OpFoldResult FormatCharOp::fold(FoldAdaptor adaptor) {
172 auto width = getValue().getType().getIntOrFloatBitWidth();
178 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
179 auto intValue = intAttr.getValue().getZExtValue();
180 return StringAttr::get(getContext(), Twine(
static_cast<char>(intValue)));
187 assert(!lits.empty() &&
"No literals to concatenate");
188 if (lits.size() == 1)
190 SmallString<64> newLit;
191 for (
auto lit : lits)
196 OpFoldResult FormatStringConcatOp::fold(FoldAdaptor adaptor) {
197 if (getNumOperands() == 0)
199 if (getNumOperands() == 1) {
201 if (getResult() == getOperand(0))
203 return getOperand(0);
207 SmallVector<StringRef> lits;
208 for (
auto attr : adaptor.getInputs()) {
209 auto lit = dyn_cast_or_null<StringAttr>(attr);
217 LogicalResult FormatStringConcatOp::getFlattenedInputs(
218 llvm::SmallVectorImpl<Value> &flatOperands) {
219 llvm::SmallMapVector<FormatStringConcatOp, unsigned, 4> concatStack;
220 bool isCyclic =
false;
224 concatStack.insert({*
this, 0});
225 while (!concatStack.empty()) {
226 auto &top = concatStack.back();
227 auto currentConcat = top.first;
228 unsigned operandIndex = top.second;
231 while (operandIndex < currentConcat.getNumOperands()) {
232 auto currentOperand = currentConcat.getOperand(operandIndex);
234 if (
auto nextConcat =
235 currentOperand.getDefiningOp<FormatStringConcatOp>()) {
237 if (!concatStack.contains(nextConcat)) {
240 top.second = operandIndex + 1;
241 concatStack.insert({nextConcat, 0});
248 flatOperands.push_back(currentOperand);
253 if (operandIndex >= currentConcat.getNumOperands())
254 concatStack.pop_back();
257 return success(!isCyclic);
261 if (llvm::any_of(getOperands(),
262 [&](Value operand) {
return operand == getResult(); }))
263 return emitOpError(
"is infinitely recursive.");
268 PatternRewriter &rewriter) {
273 bool hasBeenFlattened =
false;
274 SmallVector<Value, 0> flatOperands;
277 flatOperands.reserve(op.getNumOperands() + 4);
278 auto isAcyclic = op.getFlattenedInputs(flatOperands);
280 if (failed(isAcyclic)) {
283 op.emitWarning(
"Cyclic concatenation detected.");
287 hasBeenFlattened =
true;
290 if (!hasBeenFlattened && op.getNumOperands() < 2)
295 SmallVector<StringRef> litSequence;
296 SmallVector<Value> newOperands;
297 newOperands.reserve(op.getNumOperands());
298 FormatLitOp prevLitOp;
300 auto oldOperands = hasBeenFlattened ? flatOperands : op.getOperands();
301 for (
auto operand : oldOperands) {
302 if (
auto litOp = operand.getDefiningOp<FormatLitOp>()) {
303 if (!litOp.getLiteral().empty()) {
305 litSequence.push_back(litOp.getLiteral());
308 if (!litSequence.empty()) {
309 if (litSequence.size() > 1) {
311 auto newLit = rewriter.createOrFold<FormatLitOp>(
312 op.getLoc(), fmtStrType,
314 newOperands.push_back(newLit);
317 newOperands.push_back(prevLitOp.getResult());
321 newOperands.push_back(operand);
326 if (!litSequence.empty()) {
327 if (litSequence.size() > 1) {
329 auto newLit = rewriter.createOrFold<FormatLitOp>(
330 op.getLoc(), fmtStrType,
332 newOperands.push_back(newLit);
335 newOperands.push_back(prevLitOp.getResult());
339 if (!hasBeenFlattened && newOperands.size() == op.getNumOperands())
342 if (newOperands.empty())
343 rewriter.replaceOpWithNewOp<FormatLitOp>(op, fmtStrType,
344 rewriter.getStringAttr(
""));
345 else if (newOperands.size() == 1)
346 rewriter.replaceOp(op, newOperands);
348 rewriter.modifyOpInPlace(op, [&]() { op->setOperands(newOperands); });
354 PatternRewriter &rewriter) {
356 if (
auto cstCond = op.getCondition().getDefiningOp<
hw::ConstantOp>()) {
357 if (cstCond.getValue().isZero()) {
358 rewriter.eraseOp(op);
367 auto *parentOp = getOperation()->getParentOp();
370 return emitOpError(
"must be within a procedural region.");
372 if (isa<hw::HWDialect>(parentOp->getDialect())) {
373 if (!isa<hw::TriggeredOp>(parentOp))
374 return emitOpError(
"must be within a procedural region.");
378 if (isa<sv::SVDialect>(parentOp->getDialect())) {
379 if (!parentOp->hasTrait<sv::ProceduralRegion>())
380 return emitOpError(
"must be within a procedural region.");
389 PatternRewriter &rewriter) {
391 if (
auto litInput = op.getInput().getDefiningOp<FormatLitOp>()) {
392 if (litInput.getLiteral().empty()) {
393 rewriter.eraseOp(op);
405 #define GET_OP_CLASSES
406 #include "circt/Dialect/Sim/Sim.cpp.inc"
assert(baseType &&"element must be base type")
static StringAttr concatLiterals(MLIRContext *ctxt, ArrayRef< StringRef > lits)
static LogicalResult canonicalize(Op op, PatternRewriter &rewriter)
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.
ParseResult parseModuleSignature(OpAsmParser &parser, SmallVectorImpl< PortParse > &args, TypeAttr &modType)
New Style parsing.
void printModuleSignatureNew(OpAsmPrinter &p, Region &body, hw::ModuleType modType, ArrayRef< Attribute > portAttrs, ArrayRef< Location > locAttrs)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.