20#include "mlir/IR/Builders.h"
21#include "mlir/IR/BuiltinTypes.h"
22#include "mlir/IR/PatternMatch.h"
23#include "mlir/IR/SymbolTable.h"
32circt::esi::ChannelType ChannelBufferOp::channelType() {
33 return getOutput().getType();
36LogicalResult ChannelBufferOp::verify() {
37 if (getInput().getType().getInner() != getOutput().getType().getInner())
38 return emitOpError(
"input and output data types must match");
39 if (getOutput().getType().getDataDelay() != 0)
40 return emitOpError(
"currently only supports channels with zero data delay");
48LogicalResult SnoopValidReadyOp::verify() {
49 ChannelType type = getInput().getType();
50 if (type.getSignaling() != ChannelSignaling::ValidReady)
51 return emitOpError(
"only supports valid-ready signaling");
52 if (type.getInner() != getData().getType())
53 return emitOpError(
"input and output types must match");
57LogicalResult SnoopValidReadyOp::inferReturnTypes(
58 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
59 DictionaryAttr attrs, mlir::PropertyRef properties,
60 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
61 auto i1 = IntegerType::get(
context, 1);
62 results.push_back(i1);
63 results.push_back(i1);
64 results.push_back(cast<ChannelType>(operands[0].getType()).getInner());
68LogicalResult SnoopTransactionOp::verify() {
69 ChannelType type = getInput().getType();
70 if (type.getInner() != getData().getType())
71 return emitOpError(
"input and output types must match");
75LogicalResult SnoopTransactionOp::inferReturnTypes(
76 MLIRContext *
context, std::optional<Location> loc, ValueRange operands,
77 DictionaryAttr attrs, mlir::PropertyRef properties,
78 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
79 auto i1 = IntegerType::get(
context, 1);
80 results.push_back(i1);
81 results.push_back(cast<ChannelType>(operands[0].getType()).getInner());
89LogicalResult FIFOOp::verify() {
90 if (getOutput().getType().getInner() != getInput().getType().getInner())
91 return emitOpError(
"input and output types must match");
99circt::esi::ChannelType PipelineStageOp::channelType() {
100 return cast<circt::esi::ChannelType>(getInput().getType());
107ParseResult WrapValidReadyOp::parse(OpAsmParser &parser,
108 OperationState &result) {
109 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
111 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 2> opList;
112 Type innerOutputType;
113 if (parser.parseOperandList(opList, 2, OpAsmParser::Delimiter::None) ||
114 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
115 parser.parseType(innerOutputType))
118 auto boolType = parser.getBuilder().getI1Type();
120 ChannelType::get(parser.getBuilder().getContext(), innerOutputType);
121 result.addTypes({outputType, boolType});
122 if (parser.resolveOperands(opList, {innerOutputType, boolType},
123 inputOperandsLoc, result.operands))
128void WrapValidReadyOp::print(OpAsmPrinter &p) {
129 p <<
" " << getRawInput() <<
", " << getValid();
130 p.printOptionalAttrDict((*this)->getAttrs());
134void WrapValidReadyOp::build(OpBuilder &b, OperationState &state, Value data,
136 build(b, state, ChannelType::get(state.getContext(),
data.getType()),
137 b.getI1Type(), data, valid);
140LogicalResult WrapValidReadyOp::verify() {
141 mlir::TypedValue<ChannelType> chanOut = getChanOutput();
142 if (chanOut.getType().getSignaling() != ChannelSignaling::ValidReady)
143 return emitOpError(
"only supports valid-ready signaling");
144 if (failed(ChannelType::verifyChannel(chanOut)))
149ParseResult UnwrapValidReadyOp::parse(OpAsmParser &parser,
150 OperationState &result) {
151 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
153 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 2> opList;
155 if (parser.parseOperandList(opList, 2, OpAsmParser::Delimiter::None) ||
156 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
157 parser.parseType(outputType))
161 ChannelType::get(parser.getBuilder().getContext(), outputType);
163 auto boolType = parser.getBuilder().getI1Type();
165 result.addTypes({inputType.getInner(), boolType});
166 if (parser.resolveOperands(opList, {inputType, boolType}, inputOperandsLoc,
172void UnwrapValidReadyOp::print(OpAsmPrinter &p) {
173 p <<
" " << getChanInput() <<
", " << getReady();
174 p.printOptionalAttrDict((*this)->getAttrs());
175 p <<
" : " << getRawOutput().getType();
178LogicalResult UnwrapValidReadyOp::verify() {
179 if (getChanInput().getType().getSignaling() != ChannelSignaling::ValidReady)
180 return emitOpError(
"only supports valid-ready signaling");
184circt::esi::ChannelType WrapValidReadyOp::channelType() {
185 return cast<circt::esi::ChannelType>(getChanOutput().getType());
188void UnwrapValidReadyOp::build(OpBuilder &b, OperationState &state,
189 Value inChan, Value ready) {
190 auto inChanType = cast<ChannelType>(inChan.getType());
191 build(b, state, inChanType.getInner(), b.getI1Type(), inChan, ready);
194circt::esi::ChannelType UnwrapValidReadyOp::channelType() {
195 return cast<circt::esi::ChannelType>(getChanInput().getType());
198circt::esi::ChannelType WrapFIFOOp::channelType() {
199 return cast<circt::esi::ChannelType>(getChanOutput().getType());
203 Type &chanInputType) {
204 auto loc = p.getCurrentLocation();
206 if (p.parseType(chType))
208 if (chType.getSignaling() != ChannelSignaling::FIFO)
209 return p.emitError(loc,
"can only wrap into FIFO type");
210 dataType = chType.getInner();
211 chanInputType = chType;
220LogicalResult WrapFIFOOp::verify() {
221 if (getChanOutput().getType().getSignaling() != ChannelSignaling::FIFO)
222 return emitOpError(
"only supports FIFO signaling");
226circt::esi::ChannelType UnwrapFIFOOp::channelType() {
227 return cast<circt::esi::ChannelType>(getChanInput().getType());
230LogicalResult UnwrapFIFOOp::verify() {
231 if (getChanInput().getType().getSignaling() != ChannelSignaling::FIFO)
232 return emitOpError(
"only supports FIFO signaling");
237UnwrapFIFOOp::inferReturnTypes(MLIRContext *
context, std::optional<Location>,
238 ValueRange operands, DictionaryAttr,
239 mlir::PropertyRef, mlir::RegionRange,
240 SmallVectorImpl<Type> &inferredResulTypes) {
241 inferredResulTypes.push_back(
242 cast<ChannelType>(operands[0].getType()).getInner());
243 inferredResulTypes.push_back(
244 IntegerType::get(
context, 1, IntegerType::Signless));
252circt::esi::ChannelType WrapValidOnlyOp::channelType() {
253 return cast<circt::esi::ChannelType>(getChanOutput().getType());
257WrapValidOnlyOp::inferReturnTypes(MLIRContext *
context, std::optional<Location>,
258 ValueRange operands, DictionaryAttr,
259 mlir::PropertyRef, mlir::RegionRange,
260 SmallVectorImpl<Type> &inferredResulTypes) {
261 auto chanType = ChannelType::get(
context, operands[0].getType(),
262 ChannelSignaling::ValidOnly, 0);
263 inferredResulTypes.push_back(chanType);
267circt::esi::ChannelType UnwrapValidOnlyOp::channelType() {
268 return cast<circt::esi::ChannelType>(getChanInput().getType());
271LogicalResult UnwrapValidOnlyOp::verify() {
272 if (getChanInput().getType().getSignaling() != ChannelSignaling::ValidOnly)
273 return emitOpError(
"only supports ValidOnly signaling");
277LogicalResult UnwrapValidOnlyOp::inferReturnTypes(
278 MLIRContext *
context, std::optional<Location>, ValueRange operands,
279 DictionaryAttr, mlir::PropertyRef, mlir::RegionRange,
280 SmallVectorImpl<Type> &inferredResulTypes) {
281 inferredResulTypes.push_back(
282 cast<ChannelType>(operands[0].getType()).getInner());
283 inferredResulTypes.push_back(
284 IntegerType::get(
context, 1, IntegerType::Signless));
291 if (!iface.lookupSymbol<InterfaceSignalOp>(
"valid"))
293 if (!iface.lookupSymbol<InterfaceSignalOp>(
"ready"))
295 auto dataSig = iface.lookupSymbol<InterfaceSignalOp>(
"data");
298 return dataSig.getType();
305 circt::sv::ModportType modportType,
306 ChannelType chanType) {
308 SymbolTable::lookupNearestSymbolFrom<circt::sv::InterfaceModportOp>(
309 op, modportType.getModport());
311 return op->emitError(
"Could not find modport ")
312 << modportType.getModport() <<
" in symbol table.";
313 auto iface = cast<circt::sv::InterfaceOp>(modport->getParentOp());
316 return op->emitOpError(
"Interface is not a valid ESI interface.");
317 if (esiDataType != chanType.getInner())
318 return op->emitOpError(
"Operation specifies ")
319 << chanType <<
" but type inside doesn't match interface data type "
320 << esiDataType <<
".";
324LogicalResult WrapSVInterfaceOp::verify() {
325 auto modportType = cast<circt::sv::ModportType>(getInterfaceSink().getType());
326 auto chanType = cast<ChannelType>(getOutput().getType());
330circt::esi::ChannelType WrapSVInterfaceOp::channelType() {
331 return cast<circt::esi::ChannelType>(getOutput().getType());
334LogicalResult UnwrapSVInterfaceOp::verify() {
336 cast<circt::sv::ModportType>(getInterfaceSource().getType());
337 auto chanType = cast<ChannelType>(getChanInput().getType());
341circt::esi::ChannelType UnwrapSVInterfaceOp::channelType() {
342 return cast<circt::esi::ChannelType>(getChanInput().getType());
345LogicalResult WrapWindow::verify() {
346 Type expectedInput = getWindow().getType().getLoweredType();
347 if (expectedInput == getFrame().getType())
349 return emitOpError(
"Expected input type is ") << expectedInput;
353UnwrapWindow::inferReturnTypes(MLIRContext *, std::optional<Location>,
354 ValueRange operands, DictionaryAttr,
355 mlir::PropertyRef, mlir::RegionRange,
356 SmallVectorImpl<Type> &inferredReturnTypes) {
357 auto windowType = cast<WindowType>(operands.front().getType());
358 inferredReturnTypes.push_back(windowType.getLoweredType());
365 if (p.parseType(window))
368 frame = window.getLoweredType();
381LogicalResult CosimFromHostEndpointOp::verify() {
382 ChannelType chanType = getFromHost().getType();
383 if (chanType.getSignaling() != ChannelSignaling::ValidReady)
384 return emitOpError(
"only supports valid-ready signaling");
388LogicalResult CosimToHostEndpointOp::verify() {
389 ChannelType chanType = getToHost().getType();
390 if (chanType.getSignaling() != ChannelSignaling::ValidReady)
391 return emitOpError(
"only supports valid-ready signaling");
400static FailureOr<ServiceDeclOpInterface>
402 hw::InnerRefAttr servicePort) {
403 ModuleOp top = op->getParentOfType<mlir::ModuleOp>();
404 SymbolTable &topSyms = symbolTable.getSymbolTable(top);
406 StringAttr modName = servicePort.getModule();
407 auto serviceDecl = topSyms.lookup<ServiceDeclOpInterface>(modName);
409 return op->emitOpError(
"Could not find service declaration ")
410 << servicePort.getModuleRef();
415static FailureOr<ServicePortInfo>
417 hw::InnerRefAttr servicePort) {
419 if (failed(serviceDecl))
421 auto portInfo = serviceDecl->getPortInfo(servicePort.getName());
422 if (failed(portInfo))
423 return op->emitOpError(
"Could not locate port ") << servicePort.getName();
432 if (expected == actual)
436 return TypeSwitch<Type, LogicalResult>(expected)
438 .Case<AnyType>([&](Type) {
return success(); })
440 .Case<ChannelType>([&](ChannelType expectedChannel) {
441 auto actualChannel = dyn_cast<ChannelType>(actual);
445 actualChannel.getInner());
448 .Case<hw::StructType>([&](hw::StructType expectedStruct) {
449 auto actualStruct = dyn_cast<hw::StructType>(actual);
452 auto expectedFields = expectedStruct.getElements();
453 auto actualFields = actualStruct.getElements();
454 if (expectedFields.size() != actualFields.size())
456 for (
auto [efield, afield] : llvm::zip(expectedFields, actualFields)) {
457 if (efield.name != afield.name)
465 .Case<hw::ArrayType>([&](hw::ArrayType expectedArray) {
466 auto actualArray = dyn_cast<hw::ArrayType>(actual);
469 if (expectedArray.getNumElements() != actualArray.getNumElements())
472 actualArray.getElementType());
475 .Case<hw::UnionType>([&](hw::UnionType expectedUnion) {
476 auto actualUnion = dyn_cast<hw::UnionType>(actual);
479 auto expectedElements = expectedUnion.getElements();
480 auto actualElements = actualUnion.getElements();
481 if (expectedElements.size() != actualElements.size())
483 for (
auto [efield, afield] :
484 llvm::zip(expectedElements, actualElements)) {
485 if (efield.name != afield.name)
487 if (efield.offset != afield.offset)
495 .Case<ListType>([&](ListType expectedList) {
496 auto actualList = dyn_cast<ListType>(actual);
500 actualList.getElementType());
503 .Case<WindowType>([&](WindowType expectedWindow) {
504 auto actualWindow = dyn_cast<WindowType>(actual);
508 actualWindow.getInto());
511 .Case<hw::TypeAliasType>([&](hw::TypeAliasType expectedAlias) {
512 auto actualAlias = dyn_cast<hw::TypeAliasType>(actual);
516 actualAlias.getCanonicalType());
519 .Default([&](Type) {
return failure(); });
525 ChannelBundleType svcBundleType,
526 ChannelBundleType reqBundleType,
527 bool skipDirectionCheck) {
528 if (svcBundleType.getChannels().size() != reqBundleType.getChannels().size())
529 return req->emitOpError(
530 "Request port bundle channel count does not match service "
531 "port bundle channel count");
534 DenseMap<StringAttr, BundledChannel> declBundleChannels;
536 declBundleChannels[bc.name] = bc;
540 auto f = declBundleChannels.find(bc.name);
541 if (f == declBundleChannels.end())
542 return req->emitOpError(
543 "Request channel name not found in service port bundle");
544 if (!skipDirectionCheck && f->second.direction != bc.direction)
545 return req->emitOpError(
546 "Request channel direction does not match service "
547 "port bundle channel direction");
550 return req->emitOpError(
551 "Request channel type does not match service port "
552 "bundle channel type")
554 <<
"Service port '" << bc.name.getValue()
555 <<
"' type: " << f->second.type;
564RequestConnectionOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
571 auto svcDecl =
getServiceDecl(*
this, symbolTable, getServicePortAttr());
574 return svcDecl->verifyRequest(*svcPort, getToClient().getType(), *
this);
577LogicalResult ServiceImplementConnReqOp::verifySymbolUses(
578 SymbolTableCollection &symbolTable) {
585 auto svcDecl =
getServiceDecl(*
this, symbolTable, getServicePortAttr());
588 return svcDecl->verifyRequest(*svcPort, getToClient().getType(), *
this);
591void CustomServiceDeclOp::getPortList(SmallVectorImpl<ServicePortInfo> &ports) {
592 for (
auto toClient : getOps<ServiceDeclPortOp>())
594 hw::InnerRefAttr::
get(getSymNameAttr(), toClient.getInnerSymAttr()),
595 toClient.getToClientType()});
604 SmallVectorImpl<Type> &toChannelTypes,
605 SmallVectorImpl<Type> &fromChannelTypes, Type &type) {
607 ChannelBundleType bundleType;
608 if (parser.parseType(bundleType))
613 if (ch.direction == ChannelDirection::to)
614 toChannelTypes.push_back(ch.type);
615 else if (ch.direction == ChannelDirection::from)
616 fromChannelTypes.push_back(ch.type);
618 assert(
false &&
"Channel direction invalid");
621template <
typename T3,
typename T4>
624 p.printType(bundleType);
626void UnpackBundleOp::build(::mlir::OpBuilder &odsBuilder,
627 ::mlir::OperationState &odsState, Value bundle,
628 mlir::ValueRange fromChannels) {
630 cast<ChannelBundleType>(bundle.getType()).getChannels())
631 if (ch.direction == ChannelDirection::to)
632 odsState.addTypes(ch.type);
633 odsState.addOperands(bundle);
634 odsState.addOperands(fromChannels);
637LogicalResult PackBundleOp::verify() {
638 if (!getBundle().hasOneUse()) {
639 if (getBundle().getUsers().
empty())
640 return emitOpError(
"bundle must be used");
641 return emitOpError(
"bundle must only be used once");
645void PackBundleOp::build(::mlir::OpBuilder &odsBuilder,
646 ::mlir::OperationState &odsState,
647 ChannelBundleType bundleType,
648 mlir::ValueRange toChannels) {
649 odsState.addTypes(bundleType);
650 for (
BundledChannel ch : cast<ChannelBundleType>(bundleType).getChannels())
651 if (ch.direction == ChannelDirection::from)
652 odsState.addTypes(ch.type);
653 odsState.addOperands(toChannels);
656LogicalResult UnpackBundleOp::verify() {
657 if (!getBundle().hasOneUse()) {
658 if (getBundle().getUsers().
empty())
659 return emitOpError(
"bundle must be used");
660 return emitOpError(
"bundle must only be used once");
666 if (getNumResults() == 0)
668 setNameFn(getResult(0),
"bundle");
669 for (
auto [idx, from] :
llvm::enumerate(
llvm::make_filter_range(
671 return ch.direction == ChannelDirection::from;
673 if (idx + 1 < getNumResults())
674 setNameFn(getResult(idx + 1), from.name.getValue());
678 for (
auto [idx, to] :
llvm::enumerate(
llvm::make_filter_range(
680 return ch.direction == ChannelDirection::to;
682 if (idx < getNumResults())
683 setNameFn(getResult(idx), to.name.getValue());
689LogicalResult ESIPureModuleOp::verify() {
690 ESIDialect *esiDialect = getContext()->getLoadedDialect<ESIDialect>();
691 Block &body = getBody().front();
692 auto channelOrOutput = [](Value v) {
693 if (isa<ChannelType, ChannelBundleType>(v.getType()))
695 if (v.getUsers().empty())
697 return llvm::all_of(v.getUsers(), [](Operation *op) {
698 return isa<ESIPureModuleOutputOp>(op);
702 DenseMap<StringAttr, std::tuple<hw::ModulePort::Direction, Type, Operation *>>
704 for (Operation &op : body.getOperations()) {
705 if (igraph::InstanceOpInterface inst =
706 dyn_cast<igraph::InstanceOpInterface>(op)) {
707 if (llvm::any_of(op.getOperands(), [](Value v) {
708 return !(isa<ChannelType, ChannelBundleType>(v.getType()) ||
709 isa<ESIPureModuleInputOp>(v.getDefiningOp()));
711 return inst.emitOpError(
712 "instances in ESI pure modules can only contain channel ports or "
713 "ports driven by 'input' ops");
714 if (!llvm::all_of(op.getResults(), channelOrOutput))
715 return inst.emitOpError(
716 "instances in ESI pure modules can only contain channel ports or "
717 "drive only 'outputs'");
720 if (op.getDialect() != esiDialect)
721 return op.emitOpError(
"operation not allowed in ESI pure modules");
725 if (
auto port = dyn_cast<ESIPureModuleInputOp>(op)) {
726 auto existing = ports.find(port.getNameAttr());
727 Type portType = port.getResult().getType();
728 if (existing != ports.end()) {
729 auto [dir, type, op] = existing->getSecond();
730 if (dir != hw::ModulePort::Direction::Input || type != portType)
731 return (port.emitOpError(
"port '")
732 << port.getName() <<
"' previously declared as type " << type)
733 .attachNote(op->getLoc());
735 ports[port.getNameAttr()] = std::make_tuple(
736 hw::ModulePort::Direction::Input, portType, port.getOperation());
737 }
else if (
auto port = dyn_cast<ESIPureModuleOutputOp>(op)) {
738 auto existing = ports.find(port.getNameAttr());
739 if (existing != ports.end())
740 return (port.emitOpError(
"port '")
741 << port.getName() <<
"' previously declared")
742 .attachNote(std::get<2>(existing->getSecond())->getLoc());
743 ports[port.getNameAttr()] =
744 std::make_tuple(hw::ModulePort::Direction::Input,
745 port.getValue().getType(), port.getOperation());
751hw::ModuleType ESIPureModuleOp::getHWModuleType() {
752 return hw::ModuleType::get(getContext(), {});
755SmallVector<::circt::hw::PortInfo> ESIPureModuleOp::getPortList() {
return {}; }
757 ::llvm::report_fatal_error(
"not supported");
760size_t ESIPureModuleOp::getNumPorts() {
return 0; }
761size_t ESIPureModuleOp::getNumInputPorts() {
return 0; }
762size_t ESIPureModuleOp::getNumOutputPorts() {
return 0; }
763size_t ESIPureModuleOp::getPortIdForInputId(
size_t) {
764 assert(0 &&
"Out of bounds input port id");
767size_t ESIPureModuleOp::getPortIdForOutputId(
size_t) {
768 assert(0 &&
"Out of bounds output port id");
772SmallVector<Location> ESIPureModuleOp::getAllPortLocs() {
773 SmallVector<Location> retval;
777void ESIPureModuleOp::setAllPortLocsAttrs(ArrayRef<Attribute> locs) {
778 emitError(
"No ports for port locations");
781void ESIPureModuleOp::setAllPortNames(ArrayRef<Attribute> names) {
782 emitError(
"No ports for port naming");
785void ESIPureModuleOp::setAllPortAttrs(ArrayRef<Attribute> attrs) {
786 emitError(
"No ports for port attributes");
789void ESIPureModuleOp::removeAllPortAttrs() {
790 emitError(
"No ports for port attributes)");
793ArrayRef<Attribute> ESIPureModuleOp::getAllPortAttrs() {
return {}; }
795void ESIPureModuleOp::setHWModuleType(hw::ModuleType type) {
796 emitError(
"No ports for port types");
803StringRef ServiceImplRecordOp::getManifestClass() {
804 return getIsEngine() ?
"engine" :
"service";
807void ServiceImplRecordOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
808 auto *ctxt = getContext();
810 results.emplace_back(getAppIDAttrName(), getAppIDAttr());
812 results.emplace_back(getServiceAttrName(), getServiceAttr());
813 results.emplace_back(getServiceImplNameAttrName(), getServiceImplNameAttr());
815 for (
auto implDetail : getImplDetailsAttr().getValue())
816 results.push_back(implDetail);
819 SmallVector<Attribute, 8> reqDetails;
820 for (
auto reqDetail : getReqDetails().front().getOps<IsManifestData>())
821 reqDetails.push_back(reqDetail.getDetailsAsDict());
822 results.emplace_back(StringAttr::get(ctxt,
"clientDetails"),
823 ArrayAttr::get(ctxt, reqDetails));
827 Region &reqDetailsRegion) {
828 parser.parseOptionalRegion(reqDetailsRegion);
829 if (reqDetailsRegion.empty())
830 reqDetailsRegion.emplaceBlock();
835 Region &reqDetailsRegion) {
836 if (!reqDetailsRegion.empty() && !reqDetailsRegion.front().empty())
837 p.printRegion(reqDetailsRegion,
false,
841StringRef ServiceImplClientRecordOp::getManifestClass() {
842 return "serviceClient";
844void ServiceImplClientRecordOp::getDetails(
845 SmallVectorImpl<NamedAttribute> &results) {
849 results.emplace_back(getRelAppIDPathAttrName(), getRelAppIDPathAttr());
850 auto servicePort = getServicePortAttr();
851 results.emplace_back(
852 getServicePortAttrName(),
856 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
857 FlatSymbolRefAttr::get(servicePort.getModule())),
858 NamedAttribute(StringAttr::get(getContext(),
"port"),
859 servicePort.getName()),
861 if (
const auto &channelAssignments = getChannelAssignments())
863 NamedAttribute(getChannelAssignmentsAttrName(), *channelAssignments));
865 if (
const auto &implDetails = getImplDetails())
866 for (
const auto &implDetail : *implDetails)
867 results.push_back(implDetail);
870StringRef ServiceRequestRecordOp::getManifestClass() {
return "clientPort"; }
872void ServiceRequestRecordOp::getDetails(
873 SmallVectorImpl<NamedAttribute> &results) {
874 auto *ctxt = getContext();
875 results.emplace_back(StringAttr::get(ctxt,
"appID"), getRequestorAttr());
876 results.emplace_back(getTypeIDAttrName(), getTypeIDAttr());
877 auto servicePort = getServicePortAttr();
878 results.emplace_back(
879 getServicePortAttrName(),
883 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
884 FlatSymbolRefAttr::get(servicePort.getModule())),
885 NamedAttribute(StringAttr::get(getContext(),
"port"),
886 servicePort.getName()),
890StringRef SymbolMetadataOp::getManifestClass() {
return "symInfo"; }
892StringRef SymbolConstantsOp::getManifestClass() {
return "symConsts"; }
893void SymbolConstantsOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
894 for (
auto &attr : getConstantsAttr())
895 results.push_back(attr);
898#define GET_OP_CLASSES
899#include "circt/Dialect/ESI/ESI.cpp.inc"
901#include "circt/Dialect/ESI/ESIInterfaces.cpp.inc"
assert(baseType &&"element must be base type")
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
static std::unique_ptr< Context > context
static FailureOr< ServiceDeclOpInterface > getServiceDecl(Operation *op, SymbolTableCollection &symbolTable, hw::InnerRefAttr servicePort)
Get the port declaration op for the specified service decl, port name.
static bool parseInferWindowRet(OpAsmParser &p, Type &frame, Type &windowOut)
Determine the input type ('frame') from the return type ('window').
ParseResult parseWrapFIFOType(OpAsmParser &p, Type &dataType, Type &chanInputType)
static LogicalResult verifySVInterface(Operation *op, circt::sv::ModportType modportType, ChannelType chanType)
Verify that the modport type of 'modportArg' points to an interface which looks like an ESI interface...
void printServiceImplRecordReqDetails(OpAsmPrinter &p, ServiceImplRecordOp, Region &reqDetailsRegion)
static Type getEsiDataType(circt::sv::InterfaceOp iface)
If 'iface' looks like an ESI interface, return the inner data type.
static FailureOr< ServicePortInfo > getServicePortInfo(Operation *op, SymbolTableCollection &symbolTable, hw::InnerRefAttr servicePort)
Get the port info for the specified service decl and port name.
static void printUnPackBundleType(OpAsmPrinter &p, Operation *, T3, T4, Type bundleType)
static ParseResult parseUnPackBundleType(OpAsmParser &parser, SmallVectorImpl< Type > &toChannelTypes, SmallVectorImpl< Type > &fromChannelTypes, Type &type)
static void printInferWindowRet(OpAsmPrinter &p, Operation *, Type, Type window)
void printWrapFIFOType(OpAsmPrinter &p, WrapFIFOOp wrap, Type dataType, Type chanType)
bool parseServiceImplRecordReqDetails(OpAsmParser &parser, Region &reqDetailsRegion)
static InstancePath empty
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
mlir::Type innerType(mlir::Type type)
LogicalResult checkBundleTypeMatch(Operation *req, ChannelBundleType svcBundleType, ChannelBundleType reqBundleType, bool skipDirectionCheck)
Check that the channels on two bundles match allowing for AnyType in the 'svc' bundle.
LogicalResult checkInnerTypeMatch(Type expected, Type actual)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
Describes a service port.
This holds the name, type, direction of a module's ports.