18 #include "mlir/IR/IRMapping.h"
19 #include "mlir/IR/PatternMatch.h"
20 #include "mlir/Interfaces/FunctionImplementation.h"
21 #include "llvm/ADT/MapVector.h"
22 #include "llvm/ADT/TypeSwitch.h"
24 using namespace circt;
32 Operation *operation, ArrayAttr argNames,
33 std::function<
void(mlir::InFlightDiagnostic &)> attachNote) {
34 DenseMap<StringRef, BlockArgument> portNames;
35 DenseMap<StringRef, Operation *> memberNames;
36 DenseMap<StringRef, Operation *> localNames;
38 if (operation->getNumRegions() != 1)
39 return operation->emitError(
"required to have exactly one region");
41 bool portsVerified =
true;
43 for (
auto arg : llvm::zip(argNames, operation->getRegion(0).getArguments())) {
44 StringRef argName = std::get<0>(arg).cast<StringAttr>().getValue();
45 BlockArgument argValue = std::get<1>(arg);
47 if (portNames.count(argName)) {
48 auto diag = mlir::emitError(argValue.getLoc(),
"redefines name '")
50 diag.attachNote(portNames[argName].getLoc())
51 <<
"'" << argName <<
"' first defined here";
53 portsVerified =
false;
57 portNames.insert({argName, argValue});
61 operation->walk<mlir::WalkOrder::PreOrder>([&](Operation *op) {
62 if (isa<SCModuleOp>(op->getParentOp()))
65 if (
auto nameDeclOp = dyn_cast<SystemCNameDeclOpInterface>(op)) {
66 StringRef name = nameDeclOp.getName();
68 auto reportNameRedefinition = [&](Location firstLoc) -> WalkResult {
69 auto diag = mlir::emitError(op->getLoc(),
"redefines name '")
71 diag.attachNote(firstLoc) <<
"'" << name <<
"' first defined here";
73 return WalkResult::interrupt();
76 if (portNames.count(name))
77 return reportNameRedefinition(portNames[name].getLoc());
78 if (memberNames.count(name))
79 return reportNameRedefinition(memberNames[name]->getLoc());
80 if (localNames.count(name))
81 return reportNameRedefinition(localNames[name]->getLoc());
83 if (isa<SCModuleOp>(op->getParentOp()))
84 memberNames.insert({name, op});
86 localNames.insert({name, op});
89 return WalkResult::advance();
92 if (result.wasInterrupted() || !portsVerified)
103 return TypeSwitch<Type, hw::ModulePort::Direction>(type)
110 SCModuleOp::PortDirectionRange
112 std::function<bool(
const BlockArgument &)> predicateFn =
113 [&](
const BlockArgument &arg) ->
bool {
116 return llvm::make_filter_range(getArguments(), predicateFn);
120 SmallVector<hw::PortInfo> ports;
121 for (
int i = 0, e = getNumArguments(); i < e; ++i) {
123 info.name = getPortNames()[i].cast<StringAttr>();
126 ports.push_back(info);
131 mlir::Region *SCModuleOp::getCallableRegion() {
return &getBody(); }
133 StringRef SCModuleOp::getModuleName() {
135 ->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
139 ParseResult SCModuleOp::parse(OpAsmParser &parser, OperationState &result) {
142 (void)mlir::impl::parseOptionalVisibilityKeyword(parser, result.attributes);
145 StringAttr moduleName;
146 if (parser.parseSymbolName(moduleName, SymbolTable::getSymbolAttrName(),
151 bool isVariadic =
false;
152 SmallVector<OpAsmParser::Argument, 4> entryArgs;
153 SmallVector<Attribute> argNames;
154 SmallVector<Attribute> argLocs;
155 SmallVector<Attribute> resultNames;
156 SmallVector<DictionaryAttr> resultAttrs;
157 SmallVector<Attribute> resultLocs;
158 TypeAttr functionType;
160 parser, isVariadic, entryArgs, argNames, argLocs, resultNames,
161 resultAttrs, resultLocs, functionType)))
165 if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
168 result.addAttribute(
"portNames",
171 result.addAttribute(SCModuleOp::getFunctionTypeAttrName(result.name),
174 mlir::function_interface_impl::addArgAndResultAttrs(
175 parser.getBuilder(), result, entryArgs, resultAttrs,
176 SCModuleOp::getArgAttrsAttrName(result.name),
177 SCModuleOp::getResAttrsAttrName(result.name));
179 auto &body = *result.addRegion();
180 if (parser.parseRegion(body, entryArgs))
183 body.push_back(std::make_unique<Block>().release());
188 void SCModuleOp::print(OpAsmPrinter &p) {
192 StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
193 if (
auto visibility =
194 getOperation()->getAttrOfType<StringAttr>(visibilityAttrName))
195 p << visibility.getValue() <<
' ';
197 p.printSymbolName(SymbolTable::getSymbolName(*this).getValue());
200 bool needArgNamesAttr =
false;
202 p, *
this, getFunctionType().getInputs(),
false, {}, needArgNamesAttr);
203 mlir::function_interface_impl::printFunctionAttributes(
205 {
"portNames", getFunctionTypeAttrName(), getArgAttrsAttrName(),
206 getResAttrsAttrName()});
209 p.printRegion(getBody(),
false,
false);
213 ArrayRef<Type> SCModuleOp::getArgumentTypes() {
214 return getFunctionType().getInputs();
218 ArrayRef<Type> SCModuleOp::getResultTypes() {
219 return getFunctionType().getResults();
224 type = inoutTy.getElementType();
234 llvm_unreachable(
"Impossible port direction");
237 void SCModuleOp::build(OpBuilder &odsBuilder, OperationState &odsState,
238 StringAttr name, ArrayAttr portNames,
239 ArrayRef<Type> portTypes,
240 ArrayRef<NamedAttribute> attributes) {
241 odsState.addAttribute(getPortNamesAttrName(odsState.name), portNames);
242 Region *region = odsState.addRegion();
244 auto moduleType = odsBuilder.getFunctionType(portTypes, {});
245 odsState.addAttribute(getFunctionTypeAttrName(odsState.name),
248 odsState.addAttribute(SymbolTable::getSymbolAttrName(), name);
249 region->push_back(
new Block);
250 region->addArguments(
252 SmallVector<Location>(portTypes.size(), odsBuilder.getUnknownLoc()));
253 odsState.addAttributes(attributes);
256 void SCModuleOp::build(OpBuilder &odsBuilder, OperationState &odsState,
257 StringAttr name, ArrayRef<hw::PortInfo> ports,
258 ArrayRef<NamedAttribute> attributes) {
259 MLIRContext *ctxt = odsBuilder.getContext();
260 SmallVector<Attribute> portNames;
261 SmallVector<Type> portTypes;
262 for (
auto port : ports) {
266 build(odsBuilder, odsState, name,
ArrayAttr::get(ctxt, portNames), portTypes);
269 void SCModuleOp::build(OpBuilder &odsBuilder, OperationState &odsState,
270 StringAttr name,
const hw::ModulePortInfo &ports,
271 ArrayRef<NamedAttribute> attributes) {
272 MLIRContext *ctxt = odsBuilder.getContext();
273 SmallVector<Attribute> portNames;
274 SmallVector<Type> portTypes;
275 for (
auto port : ports) {
279 build(odsBuilder, odsState, name,
ArrayAttr::get(ctxt, portNames), portTypes);
282 void SCModuleOp::getAsmBlockArgumentNames(mlir::Region ®ion,
287 ArrayAttr portNames = getPortNames();
288 for (
size_t i = 0, e = getNumArguments(); i != e; ++i) {
289 auto str = portNames[i].cast<StringAttr>().getValue();
290 setNameFn(getArgument(i), str);
294 LogicalResult SCModuleOp::verify() {
295 if (getFunctionType().getNumResults() != 0)
297 "incorrect number of function results (always has to be 0)");
298 if (getPortNames().size() != getFunctionType().getNumInputs())
299 return emitOpError(
"incorrect number of port names");
301 for (
auto arg : getArguments()) {
302 if (!hw::type_isa<InputType, OutputType, InOutType>(arg.getType()))
303 return mlir::emitError(
305 "module port must be of type 'sc_in', 'sc_out', or 'sc_inout'");
308 for (
auto portName : getPortNames()) {
309 if (portName.cast<StringAttr>().getValue().empty())
310 return emitOpError(
"port name must not be empty");
316 LogicalResult SCModuleOp::verifyRegions() {
317 auto attachNote = [&](mlir::InFlightDiagnostic &diag) {
318 diag.attachNote(getLoc()) <<
"in module '@" << getModuleName() <<
"'";
323 CtorOp SCModuleOp::getOrCreateCtor() {
325 getBody().walk([&](Operation *op) {
326 if ((ctor = dyn_cast<CtorOp>(op)))
327 return WalkResult::interrupt();
329 return WalkResult::skip();
335 return OpBuilder(getBody()).create<CtorOp>(getLoc());
338 DestructorOp SCModuleOp::getOrCreateDestructor() {
339 DestructorOp destructor;
340 getBody().walk([&](Operation *op) {
341 if ((destructor = dyn_cast<DestructorOp>(op)))
342 return WalkResult::interrupt();
344 return WalkResult::skip();
350 return OpBuilder::atBlockEnd(getBodyBlock()).create<DestructorOp>(getLoc());
358 setNameFn(getSignal(),
getName());
365 OpFoldResult ConvertOp::fold(FoldAdaptor) {
366 if (getInput().getType() == getResult().getType())
369 if (
auto other = getInput().getDefiningOp<ConvertOp>()) {
370 Type inputType = other.getInput().getType();
371 Type intermediateType = getInput().getType();
373 if (inputType != getResult().getType())
380 if (inputSigned ^ intermediateSigned)
389 auto intermediateBw =
getBitWidth(intermediateType);
391 if (!inputBw && intermediateBw) {
393 return other.getInput();
398 if (!intermediateBw) {
400 return other.getInput();
404 return other.getInput();
406 if (inputBw && *inputBw <= 64 &&
408 .isa<IntBaseType, UIntBaseType, SignedType, UnsignedType>())
409 return other.getInput();
416 if (inputBw && intermediateBw && *inputBw <= *intermediateBw)
417 return other.getInput();
427 LogicalResult CtorOp::verify() {
428 if (getBody().getNumArguments() != 0)
429 return emitOpError(
"must not have any arguments");
439 setNameFn(getHandle(),
getName());
442 LogicalResult SCFuncOp::verify() {
443 if (getBody().getNumArguments() != 0)
444 return emitOpError(
"must not have any arguments");
454 setNameFn(getInstanceHandle(),
getName());
458 StringAttr InstanceDeclOp::getInstanceNameAttr() {
return getNameAttr(); }
461 InstanceDeclOp::getReferencedModuleCached(
const hw::HWSymbolCache *cache) {
463 if (
auto *result = cache->getDefinition(getModuleNameAttr()))
466 auto topLevelModuleOp = (*this)->getParentOfType<ModuleOp>();
467 return topLevelModuleOp.lookupSymbol(getModuleName());
471 InstanceDeclOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
473 symbolTable.lookupNearestSymbolFrom(*
this, getModuleNameAttr());
474 if (module ==
nullptr)
475 return emitError(
"cannot find module definition '")
476 << getModuleName() <<
"'";
478 auto emitError = [&](
const std::function<void(InFlightDiagnostic & diag)> &fn)
480 auto diag = emitOpError();
482 diag.attachNote(module->getLoc()) <<
"module declared here";
487 if (!isa<SCModuleOp>(module))
488 return emitError([&](
auto &diag) {
489 diag <<
"symbol reference '" << getModuleName()
490 <<
"' isn't a systemc module";
493 auto scModule = cast<SCModuleOp>(module);
496 if (scModule.getModuleName() != getInstanceType().getModuleName())
497 return emitError([&](
auto &diag) {
498 diag <<
"module names must match; expected '" << scModule.getModuleName()
499 <<
"' but got '" << getInstanceType().getModuleName().getValue()
504 ArrayRef<ModuleType::PortInfo> ports = getInstanceType().getPorts();
505 ArrayAttr modArgNames = scModule.getPortNames();
506 auto numPorts = ports.size();
507 auto expectedPortTypes = scModule.getArgumentTypes();
509 if (expectedPortTypes.size() != numPorts)
510 return emitError([&](
auto &diag) {
511 diag <<
"has a wrong number of ports; expected "
512 << expectedPortTypes.size() <<
" but got " << numPorts;
515 for (
size_t i = 0; i != numPorts; ++i) {
516 if (ports[i].type != expectedPortTypes[i]) {
517 return emitError([&](
auto &diag) {
518 diag <<
"port type #" << i <<
" must be " << expectedPortTypes[i]
519 <<
", but got " << ports[i].type;
523 if (ports[i].name != modArgNames[i])
524 return emitError([&](
auto &diag) {
525 diag <<
"port name #" << i <<
" must be " << modArgNames[i]
526 <<
", but got " << ports[i].name;
534 return cast<hw::PortList>(getReferencedModuleSlow()).getPortList();
541 LogicalResult DestructorOp::verify() {
542 if (getBody().getNumArguments() != 0)
543 return emitOpError(
"must not have any arguments");
552 ParseResult BindPortOp::parse(OpAsmParser &parser, OperationState &result) {
553 OpAsmParser::UnresolvedOperand instance, channel;
554 std::string portName;
555 if (parser.parseOperand(instance) || parser.parseLSquare() ||
556 parser.parseString(&portName))
559 auto portNameLoc = parser.getCurrentLocation();
561 if (parser.parseRSquare() || parser.parseKeyword(
"to") ||
562 parser.parseOperand(channel))
565 if (parser.parseOptionalAttrDict(result.attributes))
568 auto typeListLoc = parser.getCurrentLocation();
569 SmallVector<Type> types;
570 if (parser.parseColonTypeList(types))
573 if (types.size() != 2)
574 return parser.emitError(typeListLoc,
575 "expected a list of exactly 2 types, but got ")
578 if (parser.resolveOperand(instance, types[0], result.operands))
580 if (parser.resolveOperand(channel, types[1], result.operands))
583 if (
auto moduleType = types[0].dyn_cast<ModuleType>()) {
584 auto ports = moduleType.getPorts();
586 for (
auto port : ports) {
587 if (port.name == portName)
591 if (index >= ports.size())
592 return parser.emitError(portNameLoc,
"port name \"")
593 << portName <<
"\" not found in module";
595 result.addAttribute(
"portId", parser.getBuilder().getIndexAttr(index));
603 void BindPortOp::print(OpAsmPrinter &p) {
604 p <<
" " << getInstance() <<
"["
608 .getPorts()[getPortId().getZExtValue()]
610 <<
"] to " << getChannel();
611 p.printOptionalAttrDict((*this)->getAttrs(), {
"portId"});
612 p <<
" : " << getInstance().getType() <<
", " << getChannel().getType();
615 LogicalResult BindPortOp::verify() {
616 auto ports = getInstance().getType().cast<ModuleType>().getPorts();
617 if (getPortId().getZExtValue() >= ports.size())
618 return emitOpError(
"port #")
619 << getPortId().getZExtValue() <<
" does not exist, there are only "
620 << ports.size() <<
" ports";
623 Type portType = ports[getPortId().getZExtValue()].type;
624 Type channelType = getChannel().getType();
626 return emitOpError() << portType <<
" port cannot be bound to "
627 << channelType <<
" channel due to base type mismatch";
630 if ((portType.isa<InputType>() && channelType.isa<OutputType>()) ||
631 (portType.isa<OutputType>() && channelType.isa<InputType>()))
632 return emitOpError() << portType <<
" port cannot be bound to "
634 <<
" channel due to port direction mismatch";
639 StringRef BindPortOp::getPortName() {
643 .getPorts()[getPortId().getZExtValue()]
651 LogicalResult SensitiveOp::canonicalize(SensitiveOp op,
652 PatternRewriter &rewriter) {
653 if (op.getSensitivities().empty()) {
654 rewriter.eraseOp(op);
666 setNameFn(getVariable(),
getName());
669 ParseResult VariableOp::parse(OpAsmParser &parser, OperationState &result) {
673 result.addAttribute(
"name", nameAttr);
675 OpAsmParser::UnresolvedOperand init;
676 auto initResult = parser.parseOptionalOperand(init);
678 if (parser.parseOptionalAttrDict(result.attributes))
682 if (parser.parseColonType(variableType))
685 if (initResult.has_value()) {
686 if (parser.resolveOperand(init, variableType, result.operands))
689 result.addTypes({variableType});
694 void VariableOp::print(::mlir::OpAsmPrinter &p) {
698 p << getInit() <<
" ";
700 p.printOptionalAttrDict(getOperation()->getAttrs(), {
"name"});
701 p <<
": " << getVariable().getType();
704 LogicalResult VariableOp::verify() {
705 if (getInit() && getInit().getType() != getVariable().getType())
707 "'init' and 'variable' must have the same type, but got ")
708 << getInit().getType() <<
" and " << getVariable().getType();
718 void InteropVerilatedOp::build(OpBuilder &odsBuilder, OperationState &odsState,
719 Operation *module, StringAttr name,
721 auto mod = cast<hw::HWModuleLike>(module);
722 auto argNames = odsBuilder.getArrayAttr(mod.getInputNames());
723 auto resultNames = odsBuilder.getArrayAttr(mod.getOutputNames());
724 build(odsBuilder, odsState, mod.getHWModuleType().getOutputTypes(), name,
730 InteropVerilatedOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
732 *
this, getModuleNameAttr(), getInputs(), getResultTypes(),
733 getInputNames(), getResultNames(), ArrayAttr(), symbolTable);
740 getResultNames(), getResults());
752 LogicalResult CallOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
754 auto fnAttr = (*this)->getAttrOfType<FlatSymbolRefAttr>(
"callee");
756 return emitOpError(
"requires a 'callee' symbol reference attribute");
757 FuncOp fn = symbolTable.lookupNearestSymbolFrom<FuncOp>(*
this, fnAttr);
759 return emitOpError() <<
"'" << fnAttr.getValue()
760 <<
"' does not reference a valid function";
763 auto fnType = fn.getFunctionType();
764 if (fnType.getNumInputs() != getNumOperands())
765 return emitOpError(
"incorrect number of operands for callee");
767 for (
unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
768 if (getOperand(i).getType() != fnType.getInput(i))
769 return emitOpError(
"operand type mismatch: expected operand type ")
770 << fnType.getInput(i) <<
", but provided "
771 << getOperand(i).getType() <<
" for operand number " << i;
773 if (fnType.getNumResults() != getNumResults())
774 return emitOpError(
"incorrect number of results for callee");
776 for (
unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
777 if (getResult(i).getType() != fnType.getResult(i)) {
778 auto diag = emitOpError(
"result type mismatch at index ") << i;
779 diag.attachNote() <<
" op result types: " << getResultTypes();
780 diag.attachNote() <<
"function result types: " << fnType.getResults();
787 FunctionType CallOp::getCalleeType() {
792 LogicalResult CallOp::verify() {
793 if (getNumResults() > 1)
795 "incorrect number of function results (always has to be 0 or 1)");
805 LogicalResult CallIndirectOp::verify() {
806 if (getNumResults() > 1)
808 "incorrect number of function results (always has to be 0 or 1)");
823 FuncOp FuncOp::create(Location location, StringRef name, ArrayAttr argNames,
824 FunctionType type, ArrayRef<NamedAttribute> attrs) {
825 OpBuilder
builder(location->getContext());
826 OperationState state(location, getOperationName());
827 FuncOp::build(
builder, state, name, argNames, type, attrs);
828 return cast<FuncOp>(Operation::create(state));
831 FuncOp FuncOp::create(Location location, StringRef name, ArrayAttr argNames,
832 FunctionType type, Operation::dialect_attr_range attrs) {
833 SmallVector<NamedAttribute, 8> attrRef(attrs);
834 return create(location, name, argNames, type, ArrayRef(attrRef));
837 FuncOp FuncOp::create(Location location, StringRef name, ArrayAttr argNames,
838 FunctionType type, ArrayRef<NamedAttribute> attrs,
839 ArrayRef<DictionaryAttr> argAttrs) {
840 FuncOp func = create(location, name, argNames, type, attrs);
841 func.setAllArgAttrs(argAttrs);
845 void FuncOp::build(OpBuilder &odsBuilder, OperationState &odsState,
846 StringRef name, ArrayAttr argNames, FunctionType type,
847 ArrayRef<NamedAttribute> attrs,
848 ArrayRef<DictionaryAttr> argAttrs) {
849 odsState.addAttribute(getArgNamesAttrName(odsState.name), argNames);
850 odsState.addAttribute(SymbolTable::getSymbolAttrName(),
851 odsBuilder.getStringAttr(name));
852 odsState.addAttribute(FuncOp::getFunctionTypeAttrName(odsState.name),
854 odsState.attributes.append(attrs.begin(), attrs.end());
855 odsState.addRegion();
857 if (argAttrs.empty())
859 assert(type.getNumInputs() == argAttrs.size());
860 mlir::function_interface_impl::addArgAndResultAttrs(
861 odsBuilder, odsState, argAttrs,
862 std::nullopt, FuncOp::getArgAttrsAttrName(odsState.name),
863 FuncOp::getResAttrsAttrName(odsState.name));
866 ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
868 [](Builder &
builder, ArrayRef<Type> argTypes, ArrayRef<Type> results,
869 mlir::function_interface_impl::VariadicFlag,
870 std::string &) {
return builder.getFunctionType(argTypes, results); };
874 if (succeeded(parser.parseOptionalKeyword(
"externC")))
875 result.addAttribute(getExternCAttrName(result.name),
881 SmallVector<OpAsmParser::Argument> entryArgs;
882 SmallVector<DictionaryAttr> resultAttrs;
883 SmallVector<Type> resultTypes;
884 auto &
builder = parser.getBuilder();
887 (void)mlir::impl::parseOptionalVisibilityKeyword(parser, result.attributes);
891 if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
896 mlir::SMLoc signatureLocation = parser.getCurrentLocation();
897 bool isVariadic =
false;
898 if (mlir::function_interface_impl::parseFunctionSignature(
899 parser,
false, entryArgs, isVariadic, resultTypes, resultAttrs))
902 std::string errorMessage;
903 SmallVector<Type> argTypes;
904 argTypes.reserve(entryArgs.size());
905 for (
auto &arg : entryArgs)
906 argTypes.push_back(arg.type);
908 Type type = buildFuncType(
909 builder, argTypes, resultTypes,
910 mlir::function_interface_impl::VariadicFlag(isVariadic), errorMessage);
912 return parser.emitError(signatureLocation)
913 <<
"failed to construct function type"
914 << (errorMessage.empty() ?
"" :
": ") << errorMessage;
916 result.addAttribute(FuncOp::getFunctionTypeAttrName(result.name),
920 NamedAttrList parsedAttributes;
921 mlir::SMLoc attributeDictLocation = parser.getCurrentLocation();
922 if (parser.parseOptionalAttrDictWithKeyword(parsedAttributes))
927 for (StringRef disallowed :
928 {SymbolTable::getVisibilityAttrName(), SymbolTable::getSymbolAttrName(),
929 FuncOp::getFunctionTypeAttrName(result.name).getValue()}) {
930 if (parsedAttributes.get(disallowed))
931 return parser.emitError(attributeDictLocation,
"'")
933 <<
"' is an inferred attribute and should not be specified in the "
934 "explicit attribute dictionary";
936 result.attributes.append(parsedAttributes);
939 assert(resultAttrs.size() == resultTypes.size());
940 mlir::function_interface_impl::addArgAndResultAttrs(
941 builder, result, entryArgs, resultAttrs,
942 FuncOp::getArgAttrsAttrName(result.name),
943 FuncOp::getResAttrsAttrName(result.name));
947 auto *body = result.addRegion();
948 mlir::SMLoc loc = parser.getCurrentLocation();
949 mlir::OptionalParseResult parseResult =
950 parser.parseOptionalRegion(*body, entryArgs,
952 if (parseResult.has_value()) {
953 if (failed(*parseResult))
957 return parser.emitError(loc,
"expected non-empty function body");
962 SmallVector<Attribute> argNames;
963 if (!entryArgs.empty() && !entryArgs.front().ssaName.name.empty()) {
964 for (
auto &arg : entryArgs)
969 result.addAttribute(getArgNamesAttrName(result.name),
975 void FuncOp::print(OpAsmPrinter &p) {
979 mlir::FunctionOpInterface op = *
this;
986 op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
990 StringRef visibilityAttrName = SymbolTable::getVisibilityAttrName();
991 if (
auto visibility = op->getAttrOfType<StringAttr>(visibilityAttrName))
992 p << visibility.getValue() <<
' ';
993 p.printSymbolName(funcName);
995 ArrayRef<Type> argTypes = op.getArgumentTypes();
996 ArrayRef<Type> resultTypes = op.getResultTypes();
997 mlir::function_interface_impl::printFunctionSignature(p, op, argTypes,
false,
999 mlir::function_interface_impl::printFunctionAttributes(
1001 {visibilityAttrName,
"externC",
"argNames", getFunctionTypeAttrName(),
1002 getArgAttrsAttrName(), getResAttrsAttrName()});
1004 Region &body = op->getRegion(0);
1005 if (!body.empty()) {
1007 p.printRegion(body,
false,
1016 void FuncOp::cloneInto(FuncOp dest, IRMapping &mapper) {
1018 llvm::MapVector<StringAttr, Attribute> newAttrMap;
1019 for (
const auto &attr : dest->getAttrs())
1020 newAttrMap.insert({attr.getName(), attr.getValue()});
1021 for (
const auto &attr : (*this)->getAttrs())
1022 newAttrMap.insert({attr.getName(), attr.getValue()});
1024 auto newAttrs = llvm::to_vector(llvm::map_range(
1025 newAttrMap, [](std::pair<StringAttr, Attribute> attrPair) {
1026 return NamedAttribute(attrPair.first, attrPair.second);
1031 getBody().cloneInto(&dest.getBody(), mapper);
1039 FuncOp FuncOp::clone(IRMapping &mapper) {
1041 FuncOp newFunc = cast<FuncOp>(getOperation()->cloneWithoutRegions());
1046 if (!isExternal()) {
1047 FunctionType oldType = getFunctionType();
1049 unsigned oldNumArgs = oldType.getNumInputs();
1050 SmallVector<Type, 4> newInputs;
1051 newInputs.reserve(oldNumArgs);
1052 for (
unsigned i = 0; i != oldNumArgs; ++i)
1053 if (!mapper.contains(getArgument(i)))
1054 newInputs.push_back(oldType.getInput(i));
1058 if (newInputs.size() != oldNumArgs) {
1060 oldType.getResults()));
1062 if (ArrayAttr argAttrs = getAllArgAttrs()) {
1063 SmallVector<Attribute> newArgAttrs;
1064 newArgAttrs.reserve(newInputs.size());
1065 for (
unsigned i = 0; i != oldNumArgs; ++i)
1066 if (!mapper.contains(getArgument(i)))
1067 newArgAttrs.push_back(argAttrs[i]);
1068 newFunc.setAllArgAttrs(newArgAttrs);
1074 cloneInto(newFunc, mapper);
1078 FuncOp FuncOp::clone() {
1080 return clone(mapper);
1085 void FuncOp::getAsmBlockArgumentNames(mlir::Region ®ion,
1090 for (
auto [arg, name] : llvm::zip(getArguments(), getArgNames()))
1091 setNameFn(arg, name.cast<StringAttr>().getValue());
1094 LogicalResult FuncOp::verify() {
1095 if (getFunctionType().getNumResults() > 1)
1097 "incorrect number of function results (always has to be 0 or 1)");
1099 if (getBody().
empty())
1102 if (getArgNames().size() != getFunctionType().getNumInputs())
1103 return emitOpError(
"incorrect number of argument names");
1105 for (
auto portName : getArgNames()) {
1106 if (portName.cast<StringAttr>().getValue().empty())
1107 return emitOpError(
"arg name must not be empty");
1113 LogicalResult FuncOp::verifyRegions() {
1114 auto attachNote = [&](mlir::InFlightDiagnostic &diag) {
1115 diag.attachNote(getLoc()) <<
"in function '@" <<
getName() <<
"'";
1128 LogicalResult ReturnOp::verify() {
1129 auto function = cast<FuncOp>((*this)->getParentOp());
1132 const auto &results =
function.getFunctionType().getResults();
1133 if (getNumOperands() != results.size())
1134 return emitOpError(
"has ")
1135 << getNumOperands() <<
" operands, but enclosing function (@"
1136 <<
function.getName() <<
") returns " << results.size();
1138 for (
unsigned i = 0, e = results.size(); i != e; ++i)
1139 if (getOperand(i).getType() != results[i])
1140 return emitError() <<
"type of return operand " << i <<
" ("
1141 << getOperand(i).getType()
1142 <<
") doesn't match function result type ("
1143 << results[i] <<
")"
1144 <<
" in function @" <<
function.getName();
1154 #define GET_OP_CLASSES
1155 #include "circt/Dialect/SystemC/SystemC.cpp.inc"
assert(baseType &&"element must be base type")
static SmallVector< PortInfo > getPortList(ModuleTy &mod)
static InstancePath empty
llvm::SmallVector< StringAttr > inputs
static hw::ModulePort::Direction getDirection(Type type)
static Type wrapPortType(Type type, hw::ModulePort::Direction direction)
static LogicalResult verifyUniqueNamesInRegion(Operation *operation, ArrayAttr argNames, std::function< void(mlir::InFlightDiagnostic &)> attachNote)
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
Represents a limited word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Represents a finite word-length bit vector in SystemC as described in IEEE 1666-2011 §7....
Represents a finite word-length signed integer in SystemC as described in IEEE 1666-2011 §7....
Represents a limited word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Represents a finite word-length unsigned integer in SystemC as described in IEEE 1666-2011 §7....
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
std::string getInstanceName(mlir::func::CallOp callOp)
A helper function to get the instance name.
LogicalResult verifyInstanceOfHWModule(Operation *instance, FlatSymbolRefAttr moduleRef, OperandRange inputs, TypeRange results, ArrayAttr argNames, ArrayAttr resultNames, ArrayAttr parameters, SymbolTableCollection &symbolTable)
Combines verifyReferencedModule, verifyInputs, verifyOutputs, and verifyParameters.
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.
void printModuleSignature(OpAsmPrinter &p, Operation *op, ArrayRef< Type > argTypes, bool isVariadic, ArrayRef< Type > resultTypes, bool &needArgNamesAttr)
Print a module signature with named results.
ParseResult parseModuleFunctionSignature(OpAsmParser &parser, bool &isVariadic, SmallVectorImpl< OpAsmParser::Argument > &args, SmallVectorImpl< Attribute > &argNames, SmallVectorImpl< Attribute > &argLocs, SmallVectorImpl< Attribute > &resultNames, SmallVectorImpl< DictionaryAttr > &resultAttrs, SmallVectorImpl< Attribute > &resultLocs, TypeAttr &type)
This is a variant of mlir::parseFunctionSignature that allows names on result arguments.
circt::hw::InOutType InOutType
Type getSignalBaseType(Type type)
Get the type wrapped by a signal or port (in, inout, out) type.
std::optional< size_t > getBitWidth(Type type)
Return the bitwidth of a type.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
ParseResult parseImplicitSSAName(OpAsmParser &parser, StringAttr &attr)
Parse an implicit SSA name string attribute.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn