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::OpaqueProperties 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::OpaqueProperties 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::OpaqueProperties, 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::OpaqueProperties, 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::OpaqueProperties, 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::OpaqueProperties, 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) {
572LogicalResult ServiceImplementConnReqOp::verifySymbolUses(
573 SymbolTableCollection &symbolTable) {
581void CustomServiceDeclOp::getPortList(SmallVectorImpl<ServicePortInfo> &ports) {
582 for (
auto toClient : getOps<ServiceDeclPortOp>())
584 hw::InnerRefAttr::
get(getSymNameAttr(), toClient.getInnerSymAttr()),
585 toClient.getToClientType()});
594 SmallVectorImpl<Type> &toChannelTypes,
595 SmallVectorImpl<Type> &fromChannelTypes, Type &type) {
597 ChannelBundleType bundleType;
598 if (parser.parseType(bundleType))
603 if (ch.direction == ChannelDirection::to)
604 toChannelTypes.push_back(ch.type);
605 else if (ch.direction == ChannelDirection::from)
606 fromChannelTypes.push_back(ch.type);
608 assert(
false &&
"Channel direction invalid");
611template <
typename T3,
typename T4>
614 p.printType(bundleType);
616void UnpackBundleOp::build(::mlir::OpBuilder &odsBuilder,
617 ::mlir::OperationState &odsState, Value bundle,
618 mlir::ValueRange fromChannels) {
620 cast<ChannelBundleType>(bundle.getType()).getChannels())
621 if (ch.direction == ChannelDirection::to)
622 odsState.addTypes(ch.type);
623 odsState.addOperands(bundle);
624 odsState.addOperands(fromChannels);
627LogicalResult PackBundleOp::verify() {
628 if (!getBundle().hasOneUse()) {
629 if (getBundle().getUsers().
empty())
630 return emitOpError(
"bundle must be used");
631 return emitOpError(
"bundle must only be used once");
635void PackBundleOp::build(::mlir::OpBuilder &odsBuilder,
636 ::mlir::OperationState &odsState,
637 ChannelBundleType bundleType,
638 mlir::ValueRange toChannels) {
639 odsState.addTypes(bundleType);
640 for (
BundledChannel ch : cast<ChannelBundleType>(bundleType).getChannels())
641 if (ch.direction == ChannelDirection::from)
642 odsState.addTypes(ch.type);
643 odsState.addOperands(toChannels);
646LogicalResult UnpackBundleOp::verify() {
647 if (!getBundle().hasOneUse()) {
648 if (getBundle().getUsers().
empty())
649 return emitOpError(
"bundle must be used");
650 return emitOpError(
"bundle must only be used once");
656 if (getNumResults() == 0)
658 setNameFn(getResult(0),
"bundle");
659 for (
auto [idx, from] :
llvm::enumerate(
llvm::make_filter_range(
661 return ch.direction == ChannelDirection::from;
663 if (idx + 1 < getNumResults())
664 setNameFn(getResult(idx + 1), from.name.getValue());
668 for (
auto [idx, to] :
llvm::enumerate(
llvm::make_filter_range(
670 return ch.direction == ChannelDirection::to;
672 if (idx < getNumResults())
673 setNameFn(getResult(idx), to.name.getValue());
679LogicalResult ESIPureModuleOp::verify() {
680 ESIDialect *esiDialect = getContext()->getLoadedDialect<ESIDialect>();
681 Block &body = getBody().front();
682 auto channelOrOutput = [](Value v) {
683 if (isa<ChannelType, ChannelBundleType>(v.getType()))
685 if (v.getUsers().empty())
687 return llvm::all_of(v.getUsers(), [](Operation *op) {
688 return isa<ESIPureModuleOutputOp>(op);
692 DenseMap<StringAttr, std::tuple<hw::ModulePort::Direction, Type, Operation *>>
694 for (Operation &op : body.getOperations()) {
695 if (igraph::InstanceOpInterface inst =
696 dyn_cast<igraph::InstanceOpInterface>(op)) {
697 if (llvm::any_of(op.getOperands(), [](Value v) {
698 return !(isa<ChannelType, ChannelBundleType>(v.getType()) ||
699 isa<ESIPureModuleInputOp>(v.getDefiningOp()));
701 return inst.emitOpError(
702 "instances in ESI pure modules can only contain channel ports or "
703 "ports driven by 'input' ops");
704 if (!llvm::all_of(op.getResults(), channelOrOutput))
705 return inst.emitOpError(
706 "instances in ESI pure modules can only contain channel ports or "
707 "drive only 'outputs'");
710 if (op.getDialect() != esiDialect)
711 return op.emitOpError(
"operation not allowed in ESI pure modules");
715 if (
auto port = dyn_cast<ESIPureModuleInputOp>(op)) {
716 auto existing = ports.find(port.getNameAttr());
717 Type portType = port.getResult().getType();
718 if (existing != ports.end()) {
719 auto [dir, type, op] = existing->getSecond();
720 if (dir != hw::ModulePort::Direction::Input || type != portType)
721 return (port.emitOpError(
"port '")
722 << port.getName() <<
"' previously declared as type " << type)
723 .attachNote(op->getLoc());
725 ports[port.getNameAttr()] = std::make_tuple(
726 hw::ModulePort::Direction::Input, portType, port.getOperation());
727 }
else if (
auto port = dyn_cast<ESIPureModuleOutputOp>(op)) {
728 auto existing = ports.find(port.getNameAttr());
729 if (existing != ports.end())
730 return (port.emitOpError(
"port '")
731 << port.getName() <<
"' previously declared")
732 .attachNote(std::get<2>(existing->getSecond())->getLoc());
733 ports[port.getNameAttr()] =
734 std::make_tuple(hw::ModulePort::Direction::Input,
735 port.getValue().getType(), port.getOperation());
741hw::ModuleType ESIPureModuleOp::getHWModuleType() {
742 return hw::ModuleType::get(getContext(), {});
745SmallVector<::circt::hw::PortInfo> ESIPureModuleOp::getPortList() {
return {}; }
747 ::llvm::report_fatal_error(
"not supported");
750size_t ESIPureModuleOp::getNumPorts() {
return 0; }
751size_t ESIPureModuleOp::getNumInputPorts() {
return 0; }
752size_t ESIPureModuleOp::getNumOutputPorts() {
return 0; }
753size_t ESIPureModuleOp::getPortIdForInputId(
size_t) {
754 assert(0 &&
"Out of bounds input port id");
757size_t ESIPureModuleOp::getPortIdForOutputId(
size_t) {
758 assert(0 &&
"Out of bounds output port id");
762SmallVector<Location> ESIPureModuleOp::getAllPortLocs() {
763 SmallVector<Location> retval;
767void ESIPureModuleOp::setAllPortLocsAttrs(ArrayRef<Attribute> locs) {
768 emitError(
"No ports for port locations");
771void ESIPureModuleOp::setAllPortNames(ArrayRef<Attribute> names) {
772 emitError(
"No ports for port naming");
775void ESIPureModuleOp::setAllPortAttrs(ArrayRef<Attribute> attrs) {
776 emitError(
"No ports for port attributes");
779void ESIPureModuleOp::removeAllPortAttrs() {
780 emitError(
"No ports for port attributes)");
783ArrayRef<Attribute> ESIPureModuleOp::getAllPortAttrs() {
return {}; }
785void ESIPureModuleOp::setHWModuleType(hw::ModuleType type) {
786 emitError(
"No ports for port types");
793StringRef ServiceImplRecordOp::getManifestClass() {
794 return getIsEngine() ?
"engine" :
"service";
797void ServiceImplRecordOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
798 auto *ctxt = getContext();
800 results.emplace_back(getAppIDAttrName(), getAppIDAttr());
802 results.emplace_back(getServiceAttrName(), getServiceAttr());
803 results.emplace_back(getServiceImplNameAttrName(), getServiceImplNameAttr());
805 for (
auto implDetail : getImplDetailsAttr().getValue())
806 results.push_back(implDetail);
809 SmallVector<Attribute, 8> reqDetails;
810 for (
auto reqDetail : getReqDetails().front().getOps<IsManifestData>())
811 reqDetails.push_back(reqDetail.getDetailsAsDict());
812 results.emplace_back(StringAttr::get(ctxt,
"clientDetails"),
813 ArrayAttr::get(ctxt, reqDetails));
817 Region &reqDetailsRegion) {
818 parser.parseOptionalRegion(reqDetailsRegion);
819 if (reqDetailsRegion.empty())
820 reqDetailsRegion.emplaceBlock();
825 Region &reqDetailsRegion) {
826 if (!reqDetailsRegion.empty() && !reqDetailsRegion.front().empty())
827 p.printRegion(reqDetailsRegion,
false,
831StringRef ServiceImplClientRecordOp::getManifestClass() {
832 return "serviceClient";
834void ServiceImplClientRecordOp::getDetails(
835 SmallVectorImpl<NamedAttribute> &results) {
839 results.emplace_back(getRelAppIDPathAttrName(), getRelAppIDPathAttr());
840 auto servicePort = getServicePortAttr();
841 results.emplace_back(
842 getServicePortAttrName(),
846 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
847 FlatSymbolRefAttr::get(servicePort.getModule())),
848 NamedAttribute(StringAttr::get(getContext(),
"port"),
849 servicePort.getName()),
851 if (
const auto &channelAssignments = getChannelAssignments())
853 NamedAttribute(getChannelAssignmentsAttrName(), *channelAssignments));
855 if (
const auto &implDetails = getImplDetails())
856 for (
const auto &implDetail : *implDetails)
857 results.push_back(implDetail);
860StringRef ServiceRequestRecordOp::getManifestClass() {
return "clientPort"; }
862void ServiceRequestRecordOp::getDetails(
863 SmallVectorImpl<NamedAttribute> &results) {
864 auto *ctxt = getContext();
865 results.emplace_back(StringAttr::get(ctxt,
"appID"), getRequestorAttr());
866 results.emplace_back(getTypeIDAttrName(), getTypeIDAttr());
867 auto servicePort = getServicePortAttr();
868 results.emplace_back(
869 getServicePortAttrName(),
873 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
874 FlatSymbolRefAttr::get(servicePort.getModule())),
875 NamedAttribute(StringAttr::get(getContext(),
"port"),
876 servicePort.getName()),
880StringRef SymbolMetadataOp::getManifestClass() {
return "symInfo"; }
882StringRef SymbolConstantsOp::getManifestClass() {
return "symConsts"; }
883void SymbolConstantsOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
884 for (
auto &attr : getConstantsAttr())
885 results.push_back(attr);
888#define GET_OP_CLASSES
889#include "circt/Dialect/ESI/ESI.cpp.inc"
891#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.