17#include "mlir/Dialect/Func/IR/FuncOps.h"
18#include "mlir/IR/PatternMatch.h"
19#include "mlir/Interfaces/FunctionImplementation.h"
20#include "llvm/ADT/MapVector.h"
26ParseResult DPIFuncOp::parse(OpAsmParser &parser, OperationState &result) {
27 auto builder = parser.getBuilder();
29 (void)mlir::impl::parseOptionalVisibilityKeyword(parser, result.attributes);
33 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
37 SmallVector<hw::module_like_impl::PortParse> ports;
43 result.addAttribute(DPIFuncOp::getModuleTypeAttrName(result.name), modType);
47 auto unknownLoc = builder.getUnknownLoc();
48 SmallVector<Attribute> attrs, locs;
49 auto nonEmptyLocsFn = [unknownLoc](Attribute attr) {
50 return attr && cast<Location>(attr) != unknownLoc;
53 for (
auto &port : ports) {
54 attrs.push_back(port.attrs ? port.attrs : builder.getDictionaryAttr({}));
55 locs.push_back(port.sourceLoc ? Location(*port.sourceLoc) : unknownLoc);
58 result.addAttribute(DPIFuncOp::getPerArgumentAttrsAttrName(result.name),
59 builder.getArrayAttr(attrs));
62 if (llvm::any_of(locs, nonEmptyLocsFn))
63 result.addAttribute(DPIFuncOp::getArgumentLocsAttrName(result.name),
64 builder.getArrayAttr(locs));
67 if (failed(parser.parseOptionalAttrDictWithKeyword(result.attributes)))
74sim::DPICallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
76 symbolTable.lookupNearestSymbolFrom(*
this, getCalleeAttr());
78 return emitError(
"cannot find function declaration '")
79 << getCallee() <<
"'";
80 if (isa<func::FuncOp, sim::DPIFuncOp>(referencedOp))
82 return emitError(
"callee must be 'sim.dpi.func' or 'func.func' but got '")
83 << referencedOp->getName() <<
"'";
86void DPIFuncOp::print(OpAsmPrinter &p) {
90 op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
94 StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
95 if (
auto visibility = op->getAttrOfType<StringAttr>(visibilityAttrName))
96 p << visibility.getValue() <<
' ';
97 p.printSymbolName(funcName);
99 p, op->getRegion(0), op.getModuleType(),
100 getPerArgumentAttrsAttr()
101 ? ArrayRef<Attribute>(getPerArgumentAttrsAttr().getValue())
102 : ArrayRef<Attribute>{},
103 getArgumentLocs() ? SmallVector<Location>(
104 getArgumentLocs().value().getAsRange<Location>())
105 : ArrayRef<Location>{});
107 mlir::function_interface_impl::printFunctionAttributes(
109 {visibilityAttrName, getModuleTypeAttrName(),
110 getPerArgumentAttrsAttrName(), getArgumentLocsAttrName()});
113OpFoldResult FormatLiteralOp::fold(FoldAdaptor adaptor) {
114 return getLiteralAttr();
117OpFoldResult FormatDecOp::fold(FoldAdaptor adaptor) {
118 if (getValue().getType() == IntegerType::get(getContext(), 0U))
119 return StringAttr::get(getContext(),
"0");
121 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
122 SmallVector<char, 16> strBuf;
123 intAttr.getValue().toString(strBuf, 10U, getIsSigned());
125 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
126 unsigned padWidth = FormatDecOp::getDecimalWidth(width, getIsSigned());
127 padWidth = padWidth > strBuf.size() ? padWidth - strBuf.size() : 0;
129 SmallVector<char, 8> padding(padWidth,
' ');
130 return StringAttr::get(getContext(), Twine(padding) + Twine(strBuf));
135OpFoldResult FormatHexOp::fold(FoldAdaptor adaptor) {
136 if (getValue().getType() == IntegerType::get(getContext(), 0U))
137 return StringAttr::get(getContext(),
"");
139 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
140 SmallVector<char, 8> strBuf;
141 intAttr.getValue().toString(strBuf, 16U,
false,
145 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
146 unsigned padWidth = width / 4;
149 padWidth = padWidth > strBuf.size() ? padWidth - strBuf.size() : 0;
151 SmallVector<char, 8> padding(padWidth,
'0');
152 return StringAttr::get(getContext(), Twine(padding) + Twine(strBuf));
157OpFoldResult FormatBinOp::fold(FoldAdaptor adaptor) {
158 if (getValue().getType() == IntegerType::get(getContext(), 0U))
159 return StringAttr::get(getContext(),
"");
161 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
162 SmallVector<char, 32> strBuf;
163 intAttr.getValue().toString(strBuf, 2U,
false);
165 unsigned width = intAttr.getType().getIntOrFloatBitWidth();
166 unsigned padWidth = width > strBuf.size() ? width - strBuf.size() : 0;
168 SmallVector<char, 32> padding(padWidth,
'0');
169 return StringAttr::get(getContext(), Twine(padding) + Twine(strBuf));
174OpFoldResult FormatCharOp::fold(FoldAdaptor adaptor) {
175 auto width = getValue().getType().getIntOrFloatBitWidth();
179 return StringAttr::get(getContext(), Twine(
static_cast<char>(0)));
181 if (
auto intAttr = llvm::dyn_cast_or_null<IntegerAttr>(adaptor.getValue())) {
182 auto intValue = intAttr.getValue().getZExtValue();
183 return StringAttr::get(getContext(), Twine(
static_cast<char>(intValue)));
190 assert(!lits.empty() &&
"No literals to concatenate");
191 if (lits.size() == 1)
192 return StringAttr::get(ctxt, lits.front());
193 SmallString<64> newLit;
194 for (
auto lit : lits)
196 return StringAttr::get(ctxt, newLit);
199OpFoldResult FormatStringConcatOp::fold(FoldAdaptor adaptor) {
200 if (getNumOperands() == 0)
201 return StringAttr::get(getContext(),
"");
202 if (getNumOperands() == 1) {
204 if (getResult() == getOperand(0))
206 return getOperand(0);
210 SmallVector<StringRef> lits;
211 for (
auto attr : adaptor.getInputs()) {
212 auto lit = dyn_cast_or_null<StringAttr>(attr);
220LogicalResult FormatStringConcatOp::getFlattenedInputs(
221 llvm::SmallVectorImpl<Value> &flatOperands) {
222 llvm::SmallMapVector<FormatStringConcatOp, unsigned, 4> concatStack;
223 bool isCyclic =
false;
227 concatStack.insert({*
this, 0});
228 while (!concatStack.empty()) {
229 auto &top = concatStack.back();
230 auto currentConcat = top.first;
231 unsigned operandIndex = top.second;
234 while (operandIndex < currentConcat.getNumOperands()) {
235 auto currentOperand = currentConcat.getOperand(operandIndex);
237 if (
auto nextConcat =
238 currentOperand.getDefiningOp<FormatStringConcatOp>()) {
240 if (!concatStack.contains(nextConcat)) {
243 top.second = operandIndex + 1;
244 concatStack.insert({nextConcat, 0});
251 flatOperands.push_back(currentOperand);
256 if (operandIndex >= currentConcat.getNumOperands())
257 concatStack.pop_back();
260 return success(!isCyclic);
263LogicalResult FormatStringConcatOp::verify() {
264 if (llvm::any_of(getOperands(),
265 [&](Value operand) {
return operand == getResult(); }))
266 return emitOpError(
"is infinitely recursive.");
270LogicalResult FormatStringConcatOp::canonicalize(FormatStringConcatOp op,
271 PatternRewriter &rewriter) {
273 auto fmtStrType = FormatStringType::get(op.getContext());
276 bool hasBeenFlattened =
false;
277 SmallVector<Value, 0> flatOperands;
280 flatOperands.reserve(op.getNumOperands() + 4);
281 auto isAcyclic = op.getFlattenedInputs(flatOperands);
283 if (failed(isAcyclic)) {
286 op.emitWarning(
"Cyclic concatenation detected.");
290 hasBeenFlattened =
true;
293 if (!hasBeenFlattened && op.getNumOperands() < 2)
298 SmallVector<StringRef> litSequence;
299 SmallVector<Value> newOperands;
300 newOperands.reserve(op.getNumOperands());
301 FormatLiteralOp prevLitOp;
303 auto oldOperands = hasBeenFlattened ? flatOperands : op.getOperands();
304 for (
auto operand : oldOperands) {
305 if (
auto litOp = operand.getDefiningOp<FormatLiteralOp>()) {
306 if (!litOp.getLiteral().empty()) {
308 litSequence.push_back(litOp.getLiteral());
311 if (!litSequence.empty()) {
312 if (litSequence.size() > 1) {
314 auto newLit = rewriter.createOrFold<FormatLiteralOp>(
315 op.getLoc(), fmtStrType,
317 newOperands.push_back(newLit);
320 newOperands.push_back(prevLitOp.getResult());
324 newOperands.push_back(operand);
329 if (!litSequence.empty()) {
330 if (litSequence.size() > 1) {
332 auto newLit = rewriter.createOrFold<FormatLiteralOp>(
333 op.getLoc(), fmtStrType,
335 newOperands.push_back(newLit);
338 newOperands.push_back(prevLitOp.getResult());
342 if (!hasBeenFlattened && newOperands.size() == op.getNumOperands())
345 if (newOperands.empty())
346 rewriter.replaceOpWithNewOp<FormatLiteralOp>(op, fmtStrType,
347 rewriter.getStringAttr(
""));
348 else if (newOperands.size() == 1)
349 rewriter.replaceOp(op, newOperands);
351 rewriter.modifyOpInPlace(op, [&]() { op->setOperands(newOperands); });
356LogicalResult PrintFormattedOp::canonicalize(PrintFormattedOp op,
357 PatternRewriter &rewriter) {
359 if (
auto cstCond = op.getCondition().getDefiningOp<
hw::ConstantOp>()) {
360 if (cstCond.getValue().isZero()) {
361 rewriter.eraseOp(op);
368LogicalResult PrintFormattedProcOp::verify() {
370 auto *parentOp = getOperation()->getParentOp();
373 return emitOpError(
"must be within a procedural region.");
375 if (isa_and_nonnull<hw::HWDialect>(parentOp->getDialect())) {
376 if (!isa<hw::TriggeredOp>(parentOp))
377 return emitOpError(
"must be within a procedural region.");
381 if (isa_and_nonnull<sv::SVDialect>(parentOp->getDialect())) {
383 return emitOpError(
"must be within a procedural region.");
391LogicalResult PrintFormattedProcOp::canonicalize(PrintFormattedProcOp op,
392 PatternRewriter &rewriter) {
394 if (
auto litInput = op.getInput().getDefiningOp<FormatLiteralOp>()) {
395 if (litInput.getLiteral().empty()) {
396 rewriter.eraseOp(op);
408#define GET_OP_CLASSES
409#include "circt/Dialect/Sim/Sim.cpp.inc"
assert(baseType &&"element must be base type")
static StringAttr concatLiterals(MLIRContext *ctxt, ArrayRef< StringRef > lits)
Signals that an operations regions are procedural.
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.