From 555de191616ab947dca5dec8067c38f013f33879 Mon Sep 17 00:00:00 2001 From: Mike Urbach Date: Thu, 17 Oct 2024 20:30:50 -0600 Subject: [PATCH 1/4] Bump LLVM to 92663defb1c27d809f644752d65d8ccff93a7054. (#7714) --- llvm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm b/llvm index a285ba7529fe..92663defb1c2 160000 --- a/llvm +++ b/llvm @@ -1 +1 @@ -Subproject commit a285ba7529feaa7c49890e314facb5e9f4d8dc11 +Subproject commit 92663defb1c27d809f644752d65d8ccff93a7054 From d6b191a830cb489d7bd970ed1397ea279d901179 Mon Sep 17 00:00:00 2001 From: John Demme Date: Fri, 18 Oct 2024 02:56:39 +0000 Subject: [PATCH 2/4] [ESI][Runtime] Add service context to bundle requests Pass the current services table when requesting bundle ports. Not (yet) used in CIRCT but is required for an internal DMA engine. Useful for any DMA engine but we haven't open sourced any. --- lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h | 9 ++++++++- lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h | 3 ++- lib/Dialect/ESI/runtime/cpp/include/esi/backends/Trace.h | 3 ++- lib/Dialect/ESI/runtime/cpp/include/esi/backends/Xrt.h | 3 ++- lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp | 9 ++------- lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp | 5 ++--- lib/Dialect/ESI/runtime/cpp/lib/backends/Trace.cpp | 5 ++--- lib/Dialect/ESI/runtime/cpp/lib/backends/Xrt.cpp | 5 ++--- 8 files changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h b/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h index 8713cd275120..04c4b1b4d0d6 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/Accelerator.h @@ -85,10 +85,17 @@ class AcceleratorConnection { /// Disconnect from the accelerator cleanly. virtual void disconnect(); + // While building the design, keep around a std::map of active services + // indexed by the service name. When a new service is encountered during + // descent, add it to the table (perhaps overwriting one). Modifications to + // the table only apply to the current branch, so copy this and update it at + // each level of the tree. + using ServiceTable = std::map; + /// Request the host side channel ports for a particular instance (identified /// by the AppID path). For convenience, provide the bundle type. virtual std::map - requestChannelsFor(AppIDPath, const BundleType *) = 0; + requestChannelsFor(AppIDPath, const BundleType *, const ServiceTable &) = 0; /// Return a pointer to the accelerator 'service' thread (or threads). If the /// thread(s) are not running, they will be started when this method is diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h index 0c08610ec7ec..a554e2237032 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h @@ -54,7 +54,8 @@ class CosimAccelerator : public esi::AcceleratorConnection { /// by the AppID path). For convenience, provide the bundle type and direction /// of the bundle port. virtual std::map - requestChannelsFor(AppIDPath, const BundleType *) override; + requestChannelsFor(AppIDPath, const BundleType *, + const ServiceTable &) override; // C++ doesn't have a mechanism to forward declare a nested class and we don't // want to include the generated header here. So we have to wrap it in a diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Trace.h b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Trace.h index 5cd0406e0050..c73835a9a5fa 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Trace.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Trace.h @@ -68,7 +68,8 @@ class TraceAccelerator : public esi::AcceleratorConnection { /// Request the host side channel ports for a particular instance (identified /// by the AppID path). For convenience, provide the bundle type. std::map - requestChannelsFor(AppIDPath, const BundleType *) override; + requestChannelsFor(AppIDPath, const BundleType *, + const ServiceTable &) override; protected: virtual Service *createService(Service::Type service, AppIDPath idPath, diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Xrt.h b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Xrt.h index def6b4ebf8bd..4186f04380f0 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Xrt.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/backends/Xrt.h @@ -41,7 +41,8 @@ class XrtAccelerator : public esi::AcceleratorConnection { /// by the AppID path). For convenience, provide the bundle type and direction /// of the bundle port. std::map - requestChannelsFor(AppIDPath, const BundleType *) override; + requestChannelsFor(AppIDPath, const BundleType *, + const ServiceTable &) override; protected: virtual Service *createService(Service::Type service, AppIDPath path, diff --git a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp index 6ba8de05adae..25846663760b 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp @@ -20,12 +20,7 @@ #include using namespace ::esi; - -// While building the design, keep around a std::map of active services indexed -// by the service name. When a new service is encountered during descent, add it -// to the table (perhaps overwriting one). Modifications to the table only apply -// to the current branch, so copy this and update it at each level of the tree. -using ServiceTable = std::map; +using ServiceTable = AcceleratorConnection::ServiceTable; // This is a proxy class to the manifest JSON. It is used to avoid having to // include the JSON parser in the header. Forward references don't work since @@ -454,7 +449,7 @@ Manifest::Impl::getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath, idPath.push_back(parseID(content.at("appID"))); std::map portChannels = - acc.requestChannelsFor(idPath, bundleType); + acc.requestChannelsFor(idPath, bundleType, activeServices); services::ServicePort *svcPort = svc->getPort(idPath, bundleType, portChannels, acc); diff --git a/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp b/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp index fbe884dc2e38..2ba3bd3dfa75 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp @@ -291,9 +291,8 @@ class ReadCosimChannelPort } // namespace -std::map -CosimAccelerator::requestChannelsFor(AppIDPath idPath, - const BundleType *bundleType) { +std::map CosimAccelerator::requestChannelsFor( + AppIDPath idPath, const BundleType *bundleType, const ServiceTable &) { std::map channelResults; // Find the client details for the port at 'fullPath'. diff --git a/lib/Dialect/ESI/runtime/cpp/lib/backends/Trace.cpp b/lib/Dialect/ESI/runtime/cpp/lib/backends/Trace.cpp index 4c983b62423b..4ba30c83d2c9 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/backends/Trace.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/backends/Trace.cpp @@ -257,9 +257,8 @@ TraceAccelerator::Impl::requestChannelsFor(AppIDPath idPath, return channels; } -std::map -TraceAccelerator::requestChannelsFor(AppIDPath idPath, - const BundleType *bundleType) { +std::map TraceAccelerator::requestChannelsFor( + AppIDPath idPath, const BundleType *bundleType, const ServiceTable &) { return impl->requestChannelsFor(idPath, bundleType); } diff --git a/lib/Dialect/ESI/runtime/cpp/lib/backends/Xrt.cpp b/lib/Dialect/ESI/runtime/cpp/lib/backends/Xrt.cpp index 26b7ada78384..657f1432507b 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/backends/Xrt.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/backends/Xrt.cpp @@ -100,9 +100,8 @@ class XrtMMIO : public MMIO { }; } // namespace -std::map -XrtAccelerator::requestChannelsFor(AppIDPath idPath, - const BundleType *bundleType) { +std::map XrtAccelerator::requestChannelsFor( + AppIDPath idPath, const BundleType *bundleType, const ServiceTable &) { return impl->requestChannelsFor(idPath, bundleType); } From ffc954a7f3bef6053279baf6dd31477c57f5da67 Mon Sep 17 00:00:00 2001 From: John Demme Date: Fri, 18 Oct 2024 08:31:28 +0000 Subject: [PATCH 3/4] [ESI][Runtime] Parse AppIDs into std::any In "free form" sections, parse out anything that looks like an AppID into an AppID. Not used (yet) in CIRCT, but an internal DMA engine does use it. --- lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp | 29 ++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp index 25846663760b..2fccf77566ca 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp @@ -116,17 +116,27 @@ class Manifest::Impl { // Simple JSON -> object parsers. //===----------------------------------------------------------------------===// -static AppID parseID(const nlohmann::json &jsonID) { +static std::optional parseID(const nlohmann::json &jsonID) { + if (!jsonID.is_object()) + return std::nullopt; std::optional idx; if (jsonID.contains("index")) idx = jsonID.at("index").get(); - return AppID(jsonID.at("name").get(), idx); + if (jsonID.contains("name") && jsonID.size() <= 2) + return AppID(jsonID.at("name").get(), idx); + return std::nullopt; } +static AppID parseIDChecked(const nlohmann::json &jsonID) { + std::optional id = parseID(jsonID); + if (!id) + throw std::runtime_error("Malformed manifest: invalid appID"); + return *id; +} static AppIDPath parseIDPath(const nlohmann::json &jsonIDPath) { AppIDPath ret; - for (auto &id : jsonIDPath) - ret.push_back(parseID(id)); + for (auto &idJson : jsonIDPath) + ret.push_back(parseIDChecked(idJson)); return ret; } @@ -188,6 +198,9 @@ std::any Manifest::Impl::getAny(const nlohmann::json &value) const { innerValue.dump(2)); }; + std::optional appid = parseID(value); + if (appid) + return *appid; if (!value.is_object() || !value.contains("type") || !value.contains("value")) return getValue(value); return Constant{getValue(value.at("value")), getType(value.at("type"))}; @@ -326,7 +339,7 @@ std::unique_ptr Manifest::Impl::getChildInstance(AppIDPath idPath, AcceleratorConnection &acc, ServiceTable activeServices, const nlohmann::json &child) const { - AppID childID = parseID(child.at("appID")); + AppID childID = parseIDChecked(child.at("appID")); idPath.push_back(childID); std::vector services = @@ -334,7 +347,7 @@ Manifest::Impl::getChildInstance(AppIDPath idPath, AcceleratorConnection &acc, auto children = getChildInstances(idPath, acc, activeServices, child); auto ports = getBundlePorts(acc, idPath, activeServices, child); - return std::make_unique(parseID(child.at("appID")), + return std::make_unique(parseIDChecked(child.at("appID")), getModInfo(child), std::move(children), services, ports); } @@ -344,7 +357,7 @@ Manifest::Impl::getService(AppIDPath idPath, AcceleratorConnection &acc, const nlohmann::json &svcJson, ServiceTable &activeServices) const { - AppID id = parseID(svcJson.at("appID")); + AppID id = parseIDChecked(svcJson.at("appID")); idPath.push_back(id); // Get all the client info, including the implementation details. @@ -447,7 +460,7 @@ Manifest::Impl::getBundlePorts(AcceleratorConnection &acc, AppIDPath idPath, throw std::runtime_error("Malformed manifest: type '" + typeName + "' is not a bundle type"); - idPath.push_back(parseID(content.at("appID"))); + idPath.push_back(parseIDChecked(content.at("appID"))); std::map portChannels = acc.requestChannelsFor(idPath, bundleType, activeServices); From 313ac7a40e820aaf3ae24a71d95d837d6c49d161 Mon Sep 17 00:00:00 2001 From: John Demme Date: Fri, 18 Oct 2024 02:18:14 -0700 Subject: [PATCH 4/4] [ESI] Promote and generalize 'channel assignments' (#7715) Previously, cosim store its ESI channel to cosim channel name in the `implDetails`. DMA engines to make channel communication work in real hardware need this information as well. --- frontends/PyCDE/src/pycde/bsp/common.py | 4 +- frontends/PyCDE/src/pycde/esi.py | 15 +++--- include/circt/Dialect/ESI/ESIManifest.td | 9 ++-- lib/Dialect/ESI/ESIOps.cpp | 8 ++- lib/Dialect/ESI/ESIServices.cpp | 19 ++++--- .../ESI/runtime/cpp/include/esi/Common.h | 11 ++++ lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp | 12 ++++- .../ESI/runtime/cpp/lib/backends/Cosim.cpp | 20 ++++--- test/Dialect/ESI/manifest.mlir | 54 ++++++++++++------- test/Dialect/ESI/services.mlir | 4 +- 10 files changed, 104 insertions(+), 52 deletions(-) diff --git a/frontends/PyCDE/src/pycde/bsp/common.py b/frontends/PyCDE/src/pycde/bsp/common.py index 25309a37b372..aa3a89d0bdc1 100644 --- a/frontends/PyCDE/src/pycde/bsp/common.py +++ b/frontends/PyCDE/src/pycde/bsp/common.py @@ -152,7 +152,7 @@ def build_table(bundles) -> Tuple[Dict[int, AssignableSignal], int]: for bundle in bundles.to_client_reqs: if bundle.port == 'read': table[offset] = bundle - bundle.add_record({ + bundle.add_record(details={ "offset": offset, "size": ChannelMMIO.RegisterSpace, "type": "ro" @@ -160,7 +160,7 @@ def build_table(bundles) -> Tuple[Dict[int, AssignableSignal], int]: offset += ChannelMMIO.RegisterSpace elif bundle.port == 'read_write': table[offset] = bundle - bundle.add_record({ + bundle.add_record(details={ "offset": offset, "size": ChannelMMIO.RegisterSpace, "type": "rw" diff --git a/frontends/PyCDE/src/pycde/esi.py b/frontends/PyCDE/src/pycde/esi.py index 2c4168029d5d..74d1279fb830 100644 --- a/frontends/PyCDE/src/pycde/esi.py +++ b/frontends/PyCDE/src/pycde/esi.py @@ -7,7 +7,7 @@ from .module import generator, Module, ModuleLikeBuilderBase, PortProxyBase from .signals import (BitsSignal, BundleSignal, ChannelSignal, Signal, _FromCirctValue) -from .support import _obj_to_attribute, get_user_loc, obj_to_typed_attribute +from .support import optional_dict_to_dict_attr, get_user_loc from .system import System from .types import (Any, Bits, Bundle, BundledChannel, Channel, ChannelDirection, StructType, Type, UInt, types, @@ -140,21 +140,24 @@ def __init__(self, req: raw_esi.ServiceImplementConnReqOp, self.port = hw.InnerRefAttr(req.servicePort).name.value self._bundle_to_replace: Optional[ir.OpResult] = old_value_to_replace - def add_record(self, details: Dict[str, object]): + def add_record(self, + channel_assignments: Optional[Dict] = None, + details: Optional[Dict[str, object]] = None): """Add a record to the manifest for this client request. Generally used to give the runtime necessary information about how to connect to the client through the generated service. For instance, offsets into an MMIO space.""" - ir_details: Dict[str, ir.Attribute] = {} - for k, v in details.items(): - ir_details[k] = _obj_to_attribute(v) + channel_assignments = optional_dict_to_dict_attr(channel_assignments) + details = optional_dict_to_dict_attr(details) + with get_user_loc(), ir.InsertionPoint.at_block_begin( self.rec.reqDetails.blocks[0]): raw_esi.ServiceImplClientRecordOp( self.req.relativeAppIDPath, self.req.servicePort, ir.TypeAttr.get(self.req.toClient.type), - ir_details, + channelAssignments=channel_assignments, + implDetails=details, ) @property diff --git a/include/circt/Dialect/ESI/ESIManifest.td b/include/circt/Dialect/ESI/ESIManifest.td index 6091bf7ef85d..d6a18749032e 100644 --- a/include/circt/Dialect/ESI/ESIManifest.td +++ b/include/circt/Dialect/ESI/ESIManifest.td @@ -123,16 +123,19 @@ def ServiceImplClientRecordOp : ESI_Op<"manifest.impl_conn", [ let summary = "Details of a service implementation client connection"; let description = [{ A record containing all the necessary details of how to connect to a client - which the parent service record is servicing. + which the parent service record is servicing. Emitted on a per-client bundle + basis. There shall be at most on of these records in the entire manifest for + a particular client. }]; let arguments = (ins AppIDArrayAttr:$relAppIDPath, InnerRefAttr:$servicePort, TypeAttrOf:$typeID, - DictionaryAttr:$implDetails); + OptionalAttr:$channelAssignments, + OptionalAttr:$implDetails); let assemblyFormat = [{ $relAppIDPath `req` $servicePort `(` $typeID `)` - `with` $implDetails attr-dict + (`channels` $channelAssignments^)? (`with` $implDetails^)? attr-dict }]; let extraClassDeclaration = [{ diff --git a/lib/Dialect/ESI/ESIOps.cpp b/lib/Dialect/ESI/ESIOps.cpp index bb75dd4cabdf..718ca8db443c 100644 --- a/lib/Dialect/ESI/ESIOps.cpp +++ b/lib/Dialect/ESI/ESIOps.cpp @@ -687,9 +687,13 @@ void ServiceImplClientRecordOp::getDetails( NamedAttribute(StringAttr::get(getContext(), "port"), servicePort.getName()), })); + if (const auto &channelAssignments = getChannelAssignments()) + results.push_back( + NamedAttribute(getChannelAssignmentsAttrName(), *channelAssignments)); // Don't add another level for the implementation details. - for (auto implDetail : getImplDetailsAttr().getValue()) - results.push_back(implDetail); + if (const auto &implDetails = getImplDetails()) + for (const auto &implDetail : *implDetails) + results.push_back(implDetail); } StringRef ServiceRequestRecordOp::getManifestClass() { return "clientPort"; } diff --git a/lib/Dialect/ESI/ESIServices.cpp b/lib/Dialect/ESI/ESIServices.cpp index fef0f324eef6..0dd6a846bcf7 100644 --- a/lib/Dialect/ESI/ESIServices.cpp +++ b/lib/Dialect/ESI/ESIServices.cpp @@ -76,6 +76,14 @@ instantiateCosimEndpointOps(ServiceImplementReqOp implReq, return StringAttr::get(ctxt, os.str()); }; + auto getAssignment = [&](StringAttr name, StringAttr channelName) { + DictionaryAttr assignment = b.getDictionaryAttr({ + b.getNamedAttr("type", b.getStringAttr("cosim")), + b.getNamedAttr("name", channelName), + }); + return b.getNamedAttr(name, assignment); + }; + llvm::DenseMap toClientResultNum; for (auto req : implReq.getOps()) toClientResultNum[req] = toClientResultNum.size(); @@ -97,8 +105,7 @@ instantiateCosimEndpointOps(ServiceImplementReqOp implReq, loc, ch.type, clk, rst, toStringAttr(req.getRelativeAppIDPathAttr(), ch.name)); toServerValues.push_back(cosim.getFromHost()); - channelAssignments.push_back( - b.getNamedAttr(ch.name, cosim.getIdAttr())); + channelAssignments.push_back(getAssignment(ch.name, cosim.getIdAttr())); } } @@ -113,16 +120,14 @@ instantiateCosimEndpointOps(ServiceImplementReqOp implReq, auto cosim = b.create( loc, clk, rst, pack.getFromChannels()[chanIdx++], toStringAttr(req.getRelativeAppIDPathAttr(), ch.name)); - channelAssignments.push_back( - b.getNamedAttr(ch.name, cosim.getIdAttr())); + channelAssignments.push_back(getAssignment(ch.name, cosim.getIdAttr())); } } implRecords.create( req.getLoc(), req.getRelativeAppIDPathAttr(), req.getServicePortAttr(), - TypeAttr::get(bundleType), - b.getDictionaryAttr(b.getNamedAttr( - "channel_assignments", b.getDictionaryAttr(channelAssignments)))); + TypeAttr::get(bundleType), b.getDictionaryAttr(channelAssignments), + DictionaryAttr()); } // Erase the generation request. diff --git a/lib/Dialect/ESI/runtime/cpp/include/esi/Common.h b/lib/Dialect/ESI/runtime/cpp/include/esi/Common.h index 6169054daa87..f7c82901b1f2 100644 --- a/lib/Dialect/ESI/runtime/cpp/include/esi/Common.h +++ b/lib/Dialect/ESI/runtime/cpp/include/esi/Common.h @@ -76,11 +76,22 @@ struct ServicePortDesc { std::string portName; }; +/// Details about how to connect to a particular channel. +struct ChannelAssignment { + /// The name of the type of connection. Typically, the name of the DMA engine + /// or "cosim" if a cosimulation channel is being used. + std::string type; + /// Implementation-specific options. + std::map implOptions; +}; +using ChannelAssignments = std::map; + /// A description of a hardware client. Used pretty exclusively in setting up /// the design. struct HWClientDetail { AppIDPath relPath; ServicePortDesc port; + ChannelAssignments channelAssignments; std::map implOptions; }; using HWClientDetails = std::vector; diff --git a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp index 2fccf77566ca..15e4919e70d7 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/Manifest.cpp @@ -369,7 +369,17 @@ Manifest::Impl::getService(AppIDPath idPath, AcceleratorConnection &acc, clientDetail.relPath = parseIDPath(detail.value()); else if (detail.key() == "servicePort") clientDetail.port = parseServicePort(detail.value()); - else + else if (detail.key() == "channelAssignments") { + for (auto &chan : detail.value().items()) { + ChannelAssignment chanAssign; + for (auto &assign : chan.value().items()) + if (assign.key() == "type") + chanAssign.type = assign.value(); + else + chanAssign.implOptions[assign.key()] = getAny(assign.value()); + clientDetail.channelAssignments[chan.key()] = chanAssign; + } + } else clientDetail.implOptions[detail.key()] = getAny(detail.value()); } clientDetails.push_back(clientDetail); diff --git a/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp b/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp index 2ba3bd3dfa75..106f7670e94a 100644 --- a/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp +++ b/lib/Dialect/ESI/runtime/cpp/lib/backends/Cosim.cpp @@ -455,17 +455,15 @@ Service *CosimAccelerator::createService(Service::Type svcType, if (prefix.size() > 0) prefix.pop_back(); - if (implName == "cosim") { - // Get the channel assignments for each client. - for (auto client : clients) { - AppIDPath fullClientPath = prefix + client.relPath; - std::map channelAssignments; - for (auto assignment : std::any_cast>( - client.implOptions.at("channel_assignments"))) - channelAssignments[assignment.first] = - std::any_cast(assignment.second); - clientChannelAssignments[fullClientPath] = std::move(channelAssignments); - } + // Get the channel assignments for each client. + for (auto client : clients) { + AppIDPath fullClientPath = prefix + client.relPath; + std::map channelAssignments; + for (auto assignment : client.channelAssignments) + if (assignment.second.type == "cosim") + channelAssignments[assignment.first] = std::any_cast( + assignment.second.implOptions.at("name")); + clientChannelAssignments[fullClientPath] = std::move(channelAssignments); } if (svcType == typeid(services::MMIO)) { diff --git a/test/Dialect/ESI/manifest.mlir b/test/Dialect/ESI/manifest.mlir index 03ee14d3a71b..5c6580d98225 100644 --- a/test/Dialect/ESI/manifest.mlir +++ b/test/Dialect/ESI/manifest.mlir @@ -56,12 +56,12 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // HIER-LABEL: esi.manifest.compressed <"{{.+}}"> // HIER-LABEL: esi.manifest.hier_root @top { // HIER-NEXT: esi.manifest.service_impl #esi.appid<"cosim"> svc @HostComms by "cosim" with {} { -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_tohw">] req <@HostComms::@Recv>(!esi.bundle<[!esi.channel to "recv"]>) with {channel_assignments = {recv = "loopback_inst[0].loopback_tohw.recv"}} -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_fromhw">] req <@HostComms::@Send>(!esi.bundle<[!esi.channel from "send"]>) with {channel_assignments = {send = "loopback_inst[0].loopback_fromhw.send"}} -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_fromhw_i0">] req <@HostComms::@SendI0>(!esi.bundle<[!esi.channel from "send"]>) with {channel_assignments = {send = "loopback_inst[0].loopback_fromhw_i0.send"}} -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_tohw">] req <@HostComms::@Recv>(!esi.bundle<[!esi.channel to "recv"]>) with {channel_assignments = {recv = "loopback_inst[1].loopback_tohw.recv"}} -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_fromhw">] req <@HostComms::@Send>(!esi.bundle<[!esi.channel from "send"]>) with {channel_assignments = {send = "loopback_inst[1].loopback_fromhw.send"}} -// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_fromhw_i0">] req <@HostComms::@SendI0>(!esi.bundle<[!esi.channel from "send"]>) with {channel_assignments = {send = "loopback_inst[1].loopback_fromhw_i0.send"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_tohw">] req <@HostComms::@Recv>(!esi.bundle<[!esi.channel to "recv"]>) channels {recv = {name = "loopback_inst[0].loopback_tohw.recv", type = "cosim"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_fromhw">] req <@HostComms::@Send>(!esi.bundle<[!esi.channel from "send"]>) channels {send = {name = "loopback_inst[0].loopback_fromhw.send", type = "cosim"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[0]>, #esi.appid<"loopback_fromhw_i0">] req <@HostComms::@SendI0>(!esi.bundle<[!esi.channel from "send"]>) channels {send = {name = "loopback_inst[0].loopback_fromhw_i0.send", type = "cosim"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_tohw">] req <@HostComms::@Recv>(!esi.bundle<[!esi.channel to "recv"]>) channels {recv = {name = "loopback_inst[1].loopback_tohw.recv", type = "cosim"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_fromhw">] req <@HostComms::@Send>(!esi.bundle<[!esi.channel from "send"]>) channels {send = {name = "loopback_inst[1].loopback_fromhw.send", type = "cosim"}} +// HIER-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inst"[1]>, #esi.appid<"loopback_fromhw_i0">] req <@HostComms::@SendI0>(!esi.bundle<[!esi.channel from "send"]>) channels {send = {name = "loopback_inst[1].loopback_fromhw_i0.send", type = "cosim"}} // HIER-NEXT: } // HIER-NEXT: esi.manifest.hier_node #esi.appid<"loopback_inst"[0]> mod @Loopback { // HIER-NEXT: esi.manifest.req #esi.appid<"loopback_tohw">, <@HostComms::@Recv>, !esi.bundle<[!esi.channel to "recv"]> @@ -120,8 +120,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: "serviceImplName": "cosim", // CHECK-NEXT: "clientDetails": [ // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "recv": "loopback_inst[0].loopback_tohw.recv" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "recv": { +// CHECK-NEXT: "name": "loopback_inst[0].loopback_tohw.recv", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { @@ -138,8 +141,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "send": "loopback_inst[0].loopback_fromhw.send" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "send": { +// CHECK-NEXT: "name": "loopback_inst[0].loopback_fromhw.send", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { @@ -156,8 +162,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "send": "loopback_inst[0].loopback_fromhw_i0.send" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "send": { +// CHECK-NEXT: "name": "loopback_inst[0].loopback_fromhw_i0.send", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { @@ -174,8 +183,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "recv": "loopback_inst[1].loopback_tohw.recv" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "recv": { +// CHECK-NEXT: "name": "loopback_inst[1].loopback_tohw.recv", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { @@ -192,8 +204,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "send": "loopback_inst[1].loopback_fromhw.send" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "send": { +// CHECK-NEXT: "name": "loopback_inst[1].loopback_fromhw.send", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { @@ -210,8 +225,11 @@ hw.module @top(in %clk: !seq.clock, in %rst: i1) { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { -// CHECK-NEXT: "channel_assignments": { -// CHECK-NEXT: "send": "loopback_inst[1].loopback_fromhw_i0.send" +// CHECK-NEXT: "channelAssignments": { +// CHECK-NEXT: "send": { +// CHECK-NEXT: "name": "loopback_inst[1].loopback_fromhw_i0.send", +// CHECK-NEXT: "type": "cosim" +// CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "relAppIDPath": [ // CHECK-NEXT: { diff --git a/test/Dialect/ESI/services.mlir b/test/Dialect/ESI/services.mlir index 719116eba911..7fa968507bcf 100644 --- a/test/Dialect/ESI/services.mlir +++ b/test/Dialect/ESI/services.mlir @@ -106,7 +106,7 @@ hw.module @InOutLoopback (in %clk: !seq.clock) { // CONN-NEXT: [[clk:%.+]] = esi.pure_module.input "clk" : !seq.clock // CONN-NEXT: [[rst:%.+]] = esi.pure_module.input "rst" : i1 // CONN-NEXT: esi.manifest.service_impl #esi.appid<"cosim"> svc @HostComms by "cosim" with {} { -// CONN-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inout">] req <@HostComms::@ReqResp>(!esi.bundle<[!esi.channel to "req", !esi.channel from "resp"]>) with {channel_assignments = {req = "loopback_inout.req", resp = "loopback_inout.resp"}} +// CONN-NEXT: esi.manifest.impl_conn [#esi.appid<"loopback_inout">] req <@HostComms::@ReqResp>(!esi.bundle<[!esi.channel to "req", !esi.channel from "resp"]>) channels {req = {name = "loopback_inout.req", type = "cosim"}, resp = {name = "loopback_inout.resp", type = "cosim"}} // CONN-NEXT: } // CONN-NEXT: [[r2:%.+]] = esi.cosim.from_host [[clk]], [[rst]], "loopback_inout.req" : !esi.channel // CONN-NEXT: %bundle, %resp = esi.bundle.pack [[r2]] : !esi.bundle<[!esi.channel to "req", !esi.channel from "resp"]> @@ -194,7 +194,7 @@ hw.module @CallableFunc1() { // CONN-LABEL: hw.module @CallableAccel1(in %clk : !seq.clock, in %rst : i1) { // CONN-NEXT: hw.instance "func1" @CallableFunc1(func1: %bundle: !esi.bundle<[!esi.channel to "arg", !esi.channel from "result"]>) -> () // CONN-NEXT: esi.manifest.service_impl #esi.appid<"funcComms"> svc @funcs std "esi.service.std.func" by "cosim" with {} { -// CONN-NEXT: esi.manifest.impl_conn [#esi.appid<"func1">] req <@funcs::@call>(!esi.bundle<[!esi.channel to "arg", !esi.channel from "result"]>) with {channel_assignments = {arg = "func1.arg", result = "func1.result"}} +// CONN-NEXT: esi.manifest.impl_conn [#esi.appid<"func1">] req <@funcs::@call>(!esi.bundle<[!esi.channel to "arg", !esi.channel from "result"]>) channels {arg = {name = "func1.arg", type = "cosim"}, result = {name = "func1.result", type = "cosim"}} // CONN-NEXT: } // CONN-NEXT: %0 = esi.cosim.from_host %clk, %rst, "func1.arg" : !esi.channel // CONN-NEXT: %bundle, %result = esi.bundle.pack %0 : !esi.bundle<[!esi.channel to "arg", !esi.channel from "result"]>