Skip to content

Commit 2a3e7b4

Browse files
authored
[ESI] Factor out gRPC/proto usage in Cosim backend (#9350)
To facilitate reuse of the gRPC/protobuf generated files, and to equally hide these dependencies from the user, this PR factors out all references of gRPC and `cosim.grpc.pb.h` into a stand-alone library.
1 parent 8b4d6b0 commit 2a3e7b4

File tree

6 files changed

+558
-294
lines changed

6 files changed

+558
-294
lines changed

lib/Dialect/ESI/runtime/CMakeLists.txt

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -287,48 +287,66 @@ if(ESI_COSIM)
287287
find_package(gRPC REQUIRED CONFIG)
288288
endif()
289289

290-
add_library(CosimBackend SHARED
291-
${CMAKE_CURRENT_SOURCE_DIR}/cpp/lib/backends/Cosim.cpp
290+
set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
291+
292+
# CosimRpc library - wraps gRPC/protobuf dependencies
293+
add_library(CosimRpc SHARED
294+
${CMAKE_CURRENT_SOURCE_DIR}/cpp/lib/backends/RpcClient.cpp
292295
${CMAKE_CURRENT_SOURCE_DIR}/cpp/lib/backends/RpcServer.cpp
293296
${CMAKE_CURRENT_SOURCE_DIR}/cosim.proto
294297
)
295298
set(ESICppRuntimeBackendHeaders
296299
${ESICppRuntimeBackendHeaders}
297-
${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/esi/backends/Cosim.h
300+
${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/esi/backends/RpcClient.h
298301
${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/esi/backends/RpcServer.h
299302
)
300303

301-
target_link_libraries(CosimBackend PUBLIC
304+
target_link_libraries(CosimRpc PUBLIC
302305
ESICppRuntime
303306
protobuf::libprotobuf
304307
gRPC::grpc++
305308
)
306-
set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
307-
target_include_directories(CosimBackend PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
309+
target_include_directories(CosimRpc PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
308310
protobuf_generate(
309-
TARGET CosimBackend
311+
TARGET CosimRpc
310312
PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
311313
protobuf_generate(
312-
TARGET CosimBackend
314+
TARGET CosimRpc
313315
LANGUAGE grpc
314316
GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
315317
PLUGIN "protoc-gen-grpc=\$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
316318
PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
317319

320+
321+
# CosimBackend library - the ESI backend plugin
322+
add_library(CosimBackend SHARED
323+
${CMAKE_CURRENT_SOURCE_DIR}/cpp/lib/backends/Cosim.cpp
324+
)
325+
set(ESICppRuntimeBackendHeaders
326+
${ESICppRuntimeBackendHeaders}
327+
${CMAKE_CURRENT_SOURCE_DIR}/cpp/include/esi/backends/Cosim.h
328+
)
329+
330+
target_link_libraries(CosimBackend PUBLIC
331+
ESICppRuntime
332+
CosimRpc
333+
)
334+
target_include_directories(CosimBackend PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
335+
318336
add_dependencies(ESIRuntime CosimBackend)
319337

320338
if(WIN32)
321339
# Windows cosim backend carries a lot of runtime dependencies, mainly
322340
# transitively through gRPC. Make sure they're installed as well.
323-
install(TARGETS CosimBackend
341+
install(TARGETS CosimRpc CosimBackend
324342
DESTINATION ${ESIRT_INSTALL_LIBDIR}
325343
RUNTIME_DEPENDENCIES
326344
PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-"
327345
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
328346
COMPONENT ESIRuntime
329347
)
330348
else()
331-
install(TARGETS CosimBackend
349+
install(TARGETS CosimRpc CosimBackend
332350
DESTINATION ${ESIRT_INSTALL_LIBDIR}
333351
COMPONENT ESIRuntime
334352
)

lib/Dialect/ESI/runtime/cpp/cmake/esiaccelConfig.cmake.in

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,27 @@ else()
1414
)
1515
endif()
1616

17+
add_library(esiaccel::CosimRpc SHARED IMPORTED)
18+
set_target_properties(esiaccel::CosimRpc PROPERTIES
19+
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
20+
INTERFACE_LINK_LIBRARIES esiaccel::ESICppRuntime
21+
)
22+
23+
if(WIN32)
24+
set_target_properties(esiaccel::CosimRpc PROPERTIES
25+
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.dll"
26+
IMPORTED_IMPLIB "${CMAKE_CURRENT_LIST_DIR}/../CosimRpc.lib"
27+
)
28+
else()
29+
set_target_properties(esiaccel::CosimRpc PROPERTIES
30+
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/../@ESIRT_INSTALL_LIBDIR@/libCosimRpc.so"
31+
)
32+
endif()
33+
1734
add_library(esiaccel::CosimBackend SHARED IMPORTED)
1835
set_target_properties(esiaccel::CosimBackend PROPERTIES
1936
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_LIST_DIR}/../include"
20-
INTERFACE_LINK_LIBRARIES esiaccel::ESICppRuntime
37+
INTERFACE_LINK_LIBRARIES "esiaccel::ESICppRuntime;esiaccel::CosimRpc"
2138
)
2239

2340
if(WIN32)

lib/Dialect/ESI/runtime/cpp/include/esi/backends/Cosim.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
//===----------------------------------------------------------------------===//
88
//
99
// This is a specialization of the ESI C++ API (backend) for connection into a
10-
// simulation of an ESI system. Currently uses Cap'nProto RPC, but that could
11-
// change. Requires Cap'nProto C++ library.
10+
// simulation of an ESI system. Currently uses gRPC, but that could change.
11+
// Requires gRPC C++ library.
1212
//
1313
// DO NOT EDIT!
1414
// This file is distributed as part of an ESI package. The source for this file
@@ -26,13 +26,11 @@
2626
#include <set>
2727

2828
namespace esi {
29-
namespace cosim {
30-
class ChannelDesc;
31-
}
32-
3329
namespace backends {
3430
namespace cosim {
31+
3532
class CosimEngine;
33+
class RpcClient;
3634

3735
/// Connect to an ESI simulation.
3836
class CosimAccelerator : public esi::AcceleratorConnection {
@@ -53,11 +51,6 @@ class CosimAccelerator : public esi::AcceleratorConnection {
5351
// Set the way this connection will retrieve the manifest.
5452
void setManifestMethod(ManifestMethod method);
5553

56-
// C++ doesn't have a mechanism to forward declare a nested class and we don't
57-
// want to include the generated header here. So we have to wrap it in a
58-
// forward-declared struct we write ourselves.
59-
struct StubContainer;
60-
6154
void createEngine(const std::string &engineTypeName, AppIDPath idPath,
6255
const ServiceImplDetails &details,
6356
const HWClientDetails &clients) override;
@@ -69,7 +62,7 @@ class CosimAccelerator : public esi::AcceleratorConnection {
6962
const HWClientDetails &clients) override;
7063

7164
private:
72-
StubContainer *rpcClient;
65+
std::unique_ptr<RpcClient> rpcClient;
7366

7467
// We own all channels connected to rpcClient since their lifetime is tied to
7568
// rpcClient.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===- RpcClient.h - ESI Cosim RPC client -----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains the gRPC client implementation for ESI cosimulation.
10+
// It wraps all gRPC/protobuf dependencies so they don't leak into other
11+
// headers.
12+
//
13+
// DO NOT EDIT!
14+
// This file is distributed as part of an ESI package. The source for this file
15+
// should always be modified within CIRCT (lib/dialect/ESI/runtime/cpp).
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
// NOLINTNEXTLINE(llvm-header-guard)
20+
#ifndef ESI_BACKENDS_RPCCLIENT_H
21+
#define ESI_BACKENDS_RPCCLIENT_H
22+
23+
#include "esi/Common.h"
24+
25+
#include <functional>
26+
#include <memory>
27+
#include <string>
28+
#include <vector>
29+
30+
namespace esi {
31+
namespace backends {
32+
namespace cosim {
33+
34+
/// A gRPC client for communicating with the cosimulation server.
35+
/// This class wraps all gRPC/protobuf dependencies.
36+
class RpcClient {
37+
public:
38+
RpcClient(const std::string &hostname, uint16_t port);
39+
~RpcClient();
40+
41+
// Non-copyable.
42+
RpcClient(const RpcClient &) = delete;
43+
RpcClient &operator=(const RpcClient &) = delete;
44+
45+
/// Get the ESI version from the manifest.
46+
uint32_t getEsiVersion() const;
47+
48+
/// Get the compressed manifest from the server.
49+
std::vector<uint8_t> getCompressedManifest() const;
50+
51+
/// Channel direction as reported by the server.
52+
enum class ChannelDirection { ToServer, ToClient };
53+
54+
/// Description of a channel from the server.
55+
struct ChannelDesc {
56+
std::string name;
57+
std::string type;
58+
ChannelDirection dir;
59+
};
60+
61+
/// Get the channel description for a channel name.
62+
/// Returns true if the channel was found.
63+
bool getChannelDesc(const std::string &channelName, ChannelDesc &desc) const;
64+
65+
/// List all channels available on the server.
66+
std::vector<ChannelDesc> listChannels() const;
67+
68+
/// Send a message to a server-bound channel.
69+
void writeToServer(const std::string &channelName, const MessageData &data);
70+
71+
/// Callback type for receiving messages from a client-bound channel.
72+
/// Return true if the message was consumed, false to retry.
73+
using ReadCallback = std::function<bool(const MessageData &)>;
74+
75+
/// Abstract handle for a read channel connection.
76+
/// Destructor disconnects from the channel.
77+
class ReadChannelConnection {
78+
public:
79+
virtual ~ReadChannelConnection() = default;
80+
virtual void disconnect() = 0;
81+
};
82+
83+
/// Connect to a client-bound channel and receive messages via callback.
84+
/// Returns a handle that disconnects when destroyed.
85+
std::unique_ptr<ReadChannelConnection>
86+
connectClientReceiver(const std::string &channelName, ReadCallback callback);
87+
88+
private:
89+
class Impl;
90+
std::unique_ptr<Impl> impl;
91+
};
92+
93+
} // namespace cosim
94+
} // namespace backends
95+
} // namespace esi
96+
97+
#endif // ESI_BACKENDS_RPCCLIENT_H

0 commit comments

Comments
 (0)