20#include "mlir/IR/Builders.h"
21#include "mlir/IR/BuiltinTypes.h"
22#include "mlir/IR/PatternMatch.h"
23#include "mlir/IR/SymbolTable.h"
32ParseResult ChannelBufferOp::parse(OpAsmParser &parser,
33 OperationState &result) {
34 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
36 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
37 if (parser.parseOperandList(operands, 3,
38 OpAsmParser::Delimiter::None))
42 if (parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
43 parser.parseType(innerOutputType))
46 ChannelType::get(parser.getBuilder().getContext(), innerOutputType);
47 result.addTypes({outputType});
49 auto clkTy = seq::ClockType::get(result.getContext());
50 auto i1 = IntegerType::get(result.getContext(), 1);
51 if (parser.resolveOperands(operands, {clkTy, i1, outputType},
52 inputOperandsLoc, result.operands))
57void ChannelBufferOp::print(OpAsmPrinter &p) {
58 p <<
" " << getClk() <<
", " << getRst() <<
", " << getInput();
59 p.printOptionalAttrDict((*this)->getAttrs());
63circt::esi::ChannelType ChannelBufferOp::channelType() {
64 return cast<circt::esi::ChannelType>(getInput().getType());
67LogicalResult ChannelBufferOp::verify() {
68 if (getInput().getType().getSignaling() != ChannelSignaling::ValidReady)
69 return emitOpError(
"currently only supports valid-ready signaling");
70 if (getOutput().getType().getDataDelay() != 0)
71 return emitOpError(
"currently only supports channels with zero data delay");
79LogicalResult SnoopValidReadyOp::verify() {
80 ChannelType type = getInput().getType();
81 if (type.getSignaling() != ChannelSignaling::ValidReady)
82 return emitOpError(
"only supports valid-ready signaling");
83 if (type.getInner() != getData().getType())
84 return emitOpError(
"input and output types must match");
88LogicalResult SnoopValidReadyOp::inferReturnTypes(
89 MLIRContext *context, std::optional<Location> loc, ValueRange operands,
90 DictionaryAttr attrs, mlir::OpaqueProperties properties,
91 mlir::RegionRange regions, SmallVectorImpl<Type> &results) {
92 auto i1 = IntegerType::get(context, 1);
93 results.push_back(i1);
94 results.push_back(i1);
95 results.push_back(cast<ChannelType>(operands[0].getType()).getInner());
103LogicalResult FIFOOp::verify() {
104 if (getOutput().getType().getInner() != getInput().getType().getInner())
105 return emitOpError(
"input and output types must match");
113ParseResult PipelineStageOp::parse(OpAsmParser &parser,
114 OperationState &result) {
115 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
117 SmallVector<OpAsmParser::UnresolvedOperand, 4> operands;
118 Type innerOutputType;
119 if (parser.parseOperandList(operands, 3) ||
120 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
121 parser.parseType(innerOutputType))
124 ChannelType::get(parser.getBuilder().getContext(), innerOutputType);
125 result.addTypes({type});
127 auto clkTy = seq::ClockType::get(result.getContext());
128 auto i1 = IntegerType::get(result.getContext(), 1);
129 if (parser.resolveOperands(operands, {clkTy, i1, type}, inputOperandsLoc,
135void PipelineStageOp::print(OpAsmPrinter &p) {
136 p <<
" " << getClk() <<
", " << getRst() <<
", " << getInput();
137 p.printOptionalAttrDict((*this)->getAttrs());
141circt::esi::ChannelType PipelineStageOp::channelType() {
142 return cast<circt::esi::ChannelType>(getInput().getType());
149ParseResult WrapValidReadyOp::parse(OpAsmParser &parser,
150 OperationState &result) {
151 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
153 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 2> opList;
154 Type innerOutputType;
155 if (parser.parseOperandList(opList, 2, OpAsmParser::Delimiter::None) ||
156 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
157 parser.parseType(innerOutputType))
160 auto boolType = parser.getBuilder().getI1Type();
162 ChannelType::get(parser.getBuilder().getContext(), innerOutputType);
163 result.addTypes({outputType, boolType});
164 if (parser.resolveOperands(opList, {innerOutputType, boolType},
165 inputOperandsLoc, result.operands))
170void WrapValidReadyOp::print(OpAsmPrinter &p) {
171 p <<
" " << getRawInput() <<
", " << getValid();
172 p.printOptionalAttrDict((*this)->getAttrs());
176void WrapValidReadyOp::build(OpBuilder &b, OperationState &state, Value data,
178 build(b, state, ChannelType::get(state.getContext(),
data.getType()),
179 b.getI1Type(), data, valid);
182LogicalResult WrapValidReadyOp::verify() {
183 mlir::TypedValue<ChannelType> chanOut = getChanOutput();
184 if (chanOut.getType().getSignaling() != ChannelSignaling::ValidReady)
185 return emitOpError(
"only supports valid-ready signaling");
186 if (failed(ChannelType::verifyChannel(chanOut)))
191ParseResult UnwrapValidReadyOp::parse(OpAsmParser &parser,
192 OperationState &result) {
193 llvm::SMLoc inputOperandsLoc = parser.getCurrentLocation();
195 llvm::SmallVector<OpAsmParser::UnresolvedOperand, 2> opList;
197 if (parser.parseOperandList(opList, 2, OpAsmParser::Delimiter::None) ||
198 parser.parseOptionalAttrDict(result.attributes) || parser.parseColon() ||
199 parser.parseType(outputType))
203 ChannelType::get(parser.getBuilder().getContext(), outputType);
205 auto boolType = parser.getBuilder().getI1Type();
207 result.addTypes({inputType.getInner(), boolType});
208 if (parser.resolveOperands(opList, {inputType, boolType}, inputOperandsLoc,
214void UnwrapValidReadyOp::print(OpAsmPrinter &p) {
215 p <<
" " << getChanInput() <<
", " << getReady();
216 p.printOptionalAttrDict((*this)->getAttrs());
217 p <<
" : " << getRawOutput().getType();
220LogicalResult UnwrapValidReadyOp::verify() {
221 if (getChanInput().getType().getSignaling() != ChannelSignaling::ValidReady)
222 return emitOpError(
"only supports valid-ready signaling");
226circt::esi::ChannelType WrapValidReadyOp::channelType() {
227 return cast<circt::esi::ChannelType>(getChanOutput().getType());
230void UnwrapValidReadyOp::build(OpBuilder &b, OperationState &state,
231 Value inChan, Value ready) {
232 auto inChanType = cast<ChannelType>(inChan.getType());
233 build(b, state, inChanType.getInner(), b.getI1Type(), inChan, ready);
236circt::esi::ChannelType UnwrapValidReadyOp::channelType() {
237 return cast<circt::esi::ChannelType>(getChanInput().getType());
240circt::esi::ChannelType WrapFIFOOp::channelType() {
241 return cast<circt::esi::ChannelType>(getChanOutput().getType());
245 Type &chanInputType) {
246 auto loc = p.getCurrentLocation();
248 if (p.parseType(chType))
250 if (chType.getSignaling() != ChannelSignaling::FIFO)
251 return p.emitError(loc,
"can only wrap into FIFO type");
252 dataType = chType.getInner();
253 chanInputType = chType;
262LogicalResult WrapFIFOOp::verify() {
263 if (getChanOutput().getType().getSignaling() != ChannelSignaling::FIFO)
264 return emitOpError(
"only supports FIFO signaling");
268circt::esi::ChannelType UnwrapFIFOOp::channelType() {
269 return cast<circt::esi::ChannelType>(getChanInput().getType());
272LogicalResult UnwrapFIFOOp::verify() {
273 if (getChanInput().getType().getSignaling() != ChannelSignaling::FIFO)
274 return emitOpError(
"only supports FIFO signaling");
279UnwrapFIFOOp::inferReturnTypes(MLIRContext *context, std::optional<Location>,
280 ValueRange operands, DictionaryAttr,
281 mlir::OpaqueProperties, mlir::RegionRange,
282 SmallVectorImpl<Type> &inferredResulTypes) {
283 inferredResulTypes.push_back(
284 cast<ChannelType>(operands[0].getType()).getInner());
285 inferredResulTypes.push_back(
286 IntegerType::get(context, 1, IntegerType::Signless));
293 if (!iface.lookupSymbol<InterfaceSignalOp>(
"valid"))
295 if (!iface.lookupSymbol<InterfaceSignalOp>(
"ready"))
297 auto dataSig = iface.lookupSymbol<InterfaceSignalOp>(
"data");
300 return dataSig.getType();
307 circt::sv::ModportType modportType,
308 ChannelType chanType) {
310 SymbolTable::lookupNearestSymbolFrom<circt::sv::InterfaceModportOp>(
311 op, modportType.getModport());
313 return op->emitError(
"Could not find modport ")
314 << modportType.getModport() <<
" in symbol table.";
315 auto iface = cast<circt::sv::InterfaceOp>(modport->getParentOp());
318 return op->emitOpError(
"Interface is not a valid ESI interface.");
319 if (esiDataType != chanType.getInner())
320 return op->emitOpError(
"Operation specifies ")
321 << chanType <<
" but type inside doesn't match interface data type "
322 << esiDataType <<
".";
326LogicalResult WrapSVInterfaceOp::verify() {
327 auto modportType = cast<circt::sv::ModportType>(getInterfaceSink().getType());
328 auto chanType = cast<ChannelType>(getOutput().getType());
332circt::esi::ChannelType WrapSVInterfaceOp::channelType() {
333 return cast<circt::esi::ChannelType>(getOutput().getType());
336LogicalResult UnwrapSVInterfaceOp::verify() {
338 cast<circt::sv::ModportType>(getInterfaceSource().getType());
339 auto chanType = cast<ChannelType>(getChanInput().getType());
343circt::esi::ChannelType UnwrapSVInterfaceOp::channelType() {
344 return cast<circt::esi::ChannelType>(getChanInput().getType());
347LogicalResult WrapWindow::verify() {
348 hw::UnionType expectedInput = getWindow().getType().getLoweredType();
349 if (expectedInput == getFrame().getType())
351 return emitOpError(
"Expected input type is ") << expectedInput;
355UnwrapWindow::inferReturnTypes(MLIRContext *, std::optional<Location>,
356 ValueRange operands, DictionaryAttr,
357 mlir::OpaqueProperties, mlir::RegionRange,
358 SmallVectorImpl<Type> &inferredReturnTypes) {
359 auto windowType = cast<WindowType>(operands.front().getType());
360 inferredReturnTypes.push_back(windowType.getLoweredType());
367 if (p.parseType(window))
370 frame = window.getLoweredType();
384static FailureOr<ServiceDeclOpInterface>
386 hw::InnerRefAttr servicePort) {
387 ModuleOp top = op->getParentOfType<mlir::ModuleOp>();
388 SymbolTable &topSyms = symbolTable.getSymbolTable(top);
390 StringAttr modName = servicePort.getModule();
391 auto serviceDecl = topSyms.lookup<ServiceDeclOpInterface>(modName);
393 return op->emitOpError(
"Could not find service declaration ")
394 << servicePort.getModuleRef();
399static FailureOr<ServicePortInfo>
401 hw::InnerRefAttr servicePort) {
403 if (failed(serviceDecl))
405 auto portInfo = serviceDecl->getPortInfo(servicePort.getName());
406 if (failed(portInfo))
407 return op->emitOpError(
"Could not locate port ") << servicePort.getName();
416 if (expected == actual)
420 return TypeSwitch<Type, LogicalResult>(expected)
422 .Case<AnyType>([&](Type) {
return success(); })
424 .Case<ChannelType>([&](ChannelType expectedChannel) {
425 auto actualChannel = dyn_cast<ChannelType>(actual);
429 actualChannel.getInner());
432 .Case<hw::StructType>([&](hw::StructType expectedStruct) {
433 auto actualStruct = dyn_cast<hw::StructType>(actual);
436 auto expectedFields = expectedStruct.getElements();
437 auto actualFields = actualStruct.getElements();
438 if (expectedFields.size() != actualFields.size())
440 for (
auto [efield, afield] : llvm::zip(expectedFields, actualFields)) {
441 if (efield.name != afield.name)
449 .Case<hw::ArrayType>([&](hw::ArrayType expectedArray) {
450 auto actualArray = dyn_cast<hw::ArrayType>(actual);
453 if (expectedArray.getNumElements() != actualArray.getNumElements())
456 actualArray.getElementType());
459 .Case<hw::UnionType>([&](hw::UnionType expectedUnion) {
460 auto actualUnion = dyn_cast<hw::UnionType>(actual);
463 auto expectedElements = expectedUnion.getElements();
464 auto actualElements = actualUnion.getElements();
465 if (expectedElements.size() != actualElements.size())
467 for (
auto [efield, afield] :
468 llvm::zip(expectedElements, actualElements)) {
469 if (efield.name != afield.name)
471 if (efield.offset != afield.offset)
479 .Case<ListType>([&](ListType expectedList) {
480 auto actualList = dyn_cast<ListType>(actual);
484 actualList.getElementType());
487 .Case<WindowType>([&](WindowType expectedWindow) {
488 auto actualWindow = dyn_cast<WindowType>(actual);
492 actualWindow.getInto());
495 .Case<hw::TypeAliasType>([&](hw::TypeAliasType expectedAlias) {
496 auto actualAlias = dyn_cast<hw::TypeAliasType>(actual);
500 actualAlias.getCanonicalType());
503 .Default([&](Type) {
return failure(); });
509 ChannelBundleType svcBundleType,
510 ChannelBundleType reqBundleType,
511 bool skipDirectionCheck) {
512 if (svcBundleType.getChannels().size() != reqBundleType.getChannels().size())
513 return req->emitOpError(
514 "Request port bundle channel count does not match service "
515 "port bundle channel count");
518 DenseMap<StringAttr, BundledChannel> declBundleChannels;
520 declBundleChannels[bc.name] = bc;
524 auto f = declBundleChannels.find(bc.name);
525 if (f == declBundleChannels.end())
526 return req->emitOpError(
527 "Request channel name not found in service port bundle");
528 if (!skipDirectionCheck && f->second.direction != bc.direction)
529 return req->emitOpError(
530 "Request channel direction does not match service "
531 "port bundle channel direction");
534 return req->emitOpError(
535 "Request channel type does not match service port "
536 "bundle channel type")
538 <<
"Service port '" << bc.name.getValue()
539 <<
"' type: " << f->second.type;
548RequestConnectionOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
556LogicalResult ServiceImplementConnReqOp::verifySymbolUses(
557 SymbolTableCollection &symbolTable) {
565void CustomServiceDeclOp::getPortList(SmallVectorImpl<ServicePortInfo> &ports) {
566 for (
auto toClient : getOps<ServiceDeclPortOp>())
568 hw::InnerRefAttr::
get(getSymNameAttr(), toClient.getInnerSymAttr()),
569 toClient.getToClientType()});
578 SmallVectorImpl<Type> &toChannelTypes,
579 SmallVectorImpl<Type> &fromChannelTypes, Type &type) {
581 ChannelBundleType bundleType;
582 if (parser.parseType(bundleType))
587 if (ch.direction == ChannelDirection::to)
588 toChannelTypes.push_back(ch.type);
589 else if (ch.direction == ChannelDirection::from)
590 fromChannelTypes.push_back(ch.type);
592 assert(
false &&
"Channel direction invalid");
595template <
typename T3,
typename T4>
598 p.printType(bundleType);
600void UnpackBundleOp::build(::mlir::OpBuilder &odsBuilder,
601 ::mlir::OperationState &odsState, Value bundle,
602 mlir::ValueRange fromChannels) {
604 cast<ChannelBundleType>(bundle.getType()).getChannels())
605 if (ch.direction == ChannelDirection::to)
606 odsState.addTypes(ch.type);
607 odsState.addOperands(bundle);
608 odsState.addOperands(fromChannels);
611LogicalResult PackBundleOp::verify() {
612 if (!getBundle().hasOneUse())
613 return emitOpError(
"bundles must have exactly one user");
616void PackBundleOp::build(::mlir::OpBuilder &odsBuilder,
617 ::mlir::OperationState &odsState,
618 ChannelBundleType bundleType,
619 mlir::ValueRange toChannels) {
620 odsState.addTypes(bundleType);
621 for (
BundledChannel ch : cast<ChannelBundleType>(bundleType).getChannels())
622 if (ch.direction == ChannelDirection::from)
623 odsState.addTypes(ch.type);
624 odsState.addOperands(toChannels);
627LogicalResult UnpackBundleOp::verify() {
628 if (!getBundle().hasOneUse())
629 return emitOpError(
"bundles must have exactly one user");
634 if (getNumResults() == 0)
636 setNameFn(getResult(0),
"bundle");
637 for (
auto [idx, from] :
llvm::enumerate(
llvm::make_filter_range(
639 return ch.direction == ChannelDirection::from;
641 if (idx + 1 < getNumResults())
642 setNameFn(getResult(idx + 1), from.name.getValue());
646 for (
auto [idx, to] :
llvm::enumerate(
llvm::make_filter_range(
648 return ch.direction == ChannelDirection::to;
650 if (idx < getNumResults())
651 setNameFn(getResult(idx), to.name.getValue());
657LogicalResult ESIPureModuleOp::verify() {
658 ESIDialect *esiDialect = getContext()->getLoadedDialect<ESIDialect>();
659 Block &body = getBody().front();
660 auto channelOrOutput = [](Value v) {
661 if (isa<ChannelType, ChannelBundleType>(v.getType()))
663 if (v.getUsers().empty())
665 return llvm::all_of(v.getUsers(), [](Operation *op) {
666 return isa<ESIPureModuleOutputOp>(op);
670 DenseMap<StringAttr, std::tuple<hw::ModulePort::Direction, Type, Operation *>>
672 for (Operation &op : body.getOperations()) {
673 if (igraph::InstanceOpInterface inst =
674 dyn_cast<igraph::InstanceOpInterface>(op)) {
675 if (llvm::any_of(op.getOperands(), [](Value v) {
676 return !(isa<ChannelType, ChannelBundleType>(v.getType()) ||
677 isa<ESIPureModuleInputOp>(v.getDefiningOp()));
679 return inst.emitOpError(
680 "instances in ESI pure modules can only contain channel ports or "
681 "ports driven by 'input' ops");
682 if (!llvm::all_of(op.getResults(), channelOrOutput))
683 return inst.emitOpError(
684 "instances in ESI pure modules can only contain channel ports or "
685 "drive only 'outputs'");
688 if (op.getDialect() != esiDialect)
689 return op.emitOpError(
"operation not allowed in ESI pure modules");
693 if (
auto port = dyn_cast<ESIPureModuleInputOp>(op)) {
694 auto existing = ports.find(port.getNameAttr());
695 Type portType = port.getResult().getType();
696 if (existing != ports.end()) {
697 auto [dir, type, op] = existing->getSecond();
698 if (dir != hw::ModulePort::Direction::Input || type != portType)
699 return (port.emitOpError(
"port '")
700 << port.getName() <<
"' previously declared as type " << type)
701 .attachNote(op->getLoc());
703 ports[port.getNameAttr()] = std::make_tuple(
704 hw::ModulePort::Direction::Input, portType, port.getOperation());
705 }
else if (
auto port = dyn_cast<ESIPureModuleOutputOp>(op)) {
706 auto existing = ports.find(port.getNameAttr());
707 if (existing != ports.end())
708 return (port.emitOpError(
"port '")
709 << port.getName() <<
"' previously declared")
710 .attachNote(std::get<2>(existing->getSecond())->getLoc());
711 ports[port.getNameAttr()] =
712 std::make_tuple(hw::ModulePort::Direction::Input,
713 port.getValue().getType(), port.getOperation());
719hw::ModuleType ESIPureModuleOp::getHWModuleType() {
720 return hw::ModuleType::get(getContext(), {});
723SmallVector<::circt::hw::PortInfo> ESIPureModuleOp::getPortList() {
return {}; }
725 ::llvm::report_fatal_error(
"not supported");
728size_t ESIPureModuleOp::getNumPorts() {
return 0; }
729size_t ESIPureModuleOp::getNumInputPorts() {
return 0; }
730size_t ESIPureModuleOp::getNumOutputPorts() {
return 0; }
731size_t ESIPureModuleOp::getPortIdForInputId(
size_t) {
732 assert(0 &&
"Out of bounds input port id");
735size_t ESIPureModuleOp::getPortIdForOutputId(
size_t) {
736 assert(0 &&
"Out of bounds output port id");
740SmallVector<Location> ESIPureModuleOp::getAllPortLocs() {
741 SmallVector<Location> retval;
745void ESIPureModuleOp::setAllPortLocsAttrs(ArrayRef<Attribute> locs) {
746 emitError(
"No ports for port locations");
749void ESIPureModuleOp::setAllPortNames(ArrayRef<Attribute> names) {
750 emitError(
"No ports for port naming");
753void ESIPureModuleOp::setAllPortAttrs(ArrayRef<Attribute> attrs) {
754 emitError(
"No ports for port attributes");
757void ESIPureModuleOp::removeAllPortAttrs() {
758 emitError(
"No ports for port attributes)");
761ArrayRef<Attribute> ESIPureModuleOp::getAllPortAttrs() {
return {}; }
763void ESIPureModuleOp::setHWModuleType(hw::ModuleType type) {
764 emitError(
"No ports for port types");
771StringRef ServiceImplRecordOp::getManifestClass() {
return "service"; }
773void ServiceImplRecordOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
774 auto *
ctxt = getContext();
776 results.emplace_back(getAppIDAttrName(), getAppIDAttr());
778 results.emplace_back(getServiceAttrName(), getServiceAttr());
779 results.emplace_back(getServiceImplNameAttrName(), getServiceImplNameAttr());
781 for (
auto implDetail : getImplDetailsAttr().getValue())
782 results.push_back(implDetail);
785 SmallVector<Attribute, 8> reqDetails;
786 for (
auto reqDetail : getReqDetails().front().getOps<IsManifestData>())
787 reqDetails.push_back(reqDetail.getDetailsAsDict());
788 results.emplace_back(StringAttr::get(ctxt,
"clientDetails"),
789 ArrayAttr::get(ctxt, reqDetails));
793 Region &reqDetailsRegion) {
794 parser.parseOptionalRegion(reqDetailsRegion);
795 if (reqDetailsRegion.empty())
796 reqDetailsRegion.emplaceBlock();
801 Region &reqDetailsRegion) {
802 if (!reqDetailsRegion.empty() && !reqDetailsRegion.front().empty())
803 p.printRegion(reqDetailsRegion,
false,
807StringRef ServiceImplClientRecordOp::getManifestClass() {
808 return "serviceClient";
810void ServiceImplClientRecordOp::getDetails(
811 SmallVectorImpl<NamedAttribute> &results) {
815 results.emplace_back(getRelAppIDPathAttrName(), getRelAppIDPathAttr());
816 auto servicePort = getServicePortAttr();
817 results.emplace_back(
818 getServicePortAttrName(),
822 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
823 FlatSymbolRefAttr::get(servicePort.getModule())),
824 NamedAttribute(StringAttr::get(getContext(),
"port"),
825 servicePort.getName()),
827 if (
const auto &channelAssignments = getChannelAssignments())
829 NamedAttribute(getChannelAssignmentsAttrName(), *channelAssignments));
831 if (
const auto &implDetails = getImplDetails())
832 for (
const auto &implDetail : *implDetails)
833 results.push_back(implDetail);
836StringRef ServiceRequestRecordOp::getManifestClass() {
return "clientPort"; }
838void ServiceRequestRecordOp::getDetails(
839 SmallVectorImpl<NamedAttribute> &results) {
840 auto *
ctxt = getContext();
841 results.emplace_back(StringAttr::get(ctxt,
"appID"), getRequestorAttr());
842 results.emplace_back(getTypeIDAttrName(), getTypeIDAttr());
843 auto servicePort = getServicePortAttr();
844 results.emplace_back(
845 getServicePortAttrName(),
849 NamedAttribute(StringAttr::get(getContext(),
"serviceName"),
850 FlatSymbolRefAttr::get(servicePort.getModule())),
851 NamedAttribute(StringAttr::get(getContext(),
"port"),
852 servicePort.getName()),
856StringRef SymbolMetadataOp::getManifestClass() {
return "symInfo"; }
858StringRef SymbolConstantsOp::getManifestClass() {
return "symConsts"; }
859void SymbolConstantsOp::getDetails(SmallVectorImpl<NamedAttribute> &results) {
860 for (
auto &attr : getConstantsAttr())
861 results.push_back(attr);
864#define GET_OP_CLASSES
865#include "circt/Dialect/ESI/ESI.cpp.inc"
867#include "circt/Dialect/ESI/ESIInterfaces.cpp.inc"
assert(baseType &&"element must be base type")
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
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)
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.