1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#ifndef TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
21#define TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_
22
23#include <tvm/runtime/c_runtime_api.h>
24
25#include <functional>
26#include <sstream>
27#include <string>
28#include <unordered_map>
29
30#include "minrpc_interfaces.h"
31#include "rpc_reference.h"
32
33namespace tvm {
34namespace runtime {
35
36#define PRINT_BYTES false
37
38/*!
39 * \brief Generates a user readeable log on the console
40 */
41class Logger {
42 public:
43 Logger() {}
44
45 /*!
46 * \brief this function logs a string
47 *
48 * \param s the string to be logged.
49 */
50 void Log(const char* s) { os_ << s; }
51 void Log(std::string s) { os_ << s; }
52
53 /*!
54 * \brief this function logs a numerical value
55 *
56 * \param desc adds any necessary description before the value.
57 * \param val is the value to be logged.
58 */
59 template <typename T>
60 void LogValue(const char* desc, T val) {
61 os_ << desc << val;
62 }
63
64 /*!
65 * \brief this function logs the properties of a DLDevice
66 *
67 * \param desc adds any necessary description before the DLDevice.
68 * \param dev is the pointer to the DLDevice to be logged.
69 */
70 void LogDLDevice(const char* desc, DLDevice* dev) {
71 os_ << desc << "(" << dev->device_type << "," << dev->device_id << ")";
72 }
73
74 /*!
75 * \brief this function logs the properties of a DLDataType
76 *
77 * \param desc adds any necessary description before the DLDataType.
78 * \param data is the pointer to the DLDataType to be logged.
79 */
80 void LogDLData(const char* desc, DLDataType* data) {
81 os_ << desc << "(" << (uint16_t)data->code << "," << (uint16_t)data->bits << "," << data->lanes
82 << ")";
83 }
84
85 /*!
86 * \brief this function logs a handle name.
87 *
88 * \param name is the name to be logged.
89 */
90 void LogHandleName(std::string name) {
91 if (name.length() > 0) {
92 os_ << " <" << name.c_str() << ">";
93 }
94 }
95
96 /*!
97 * \brief this function logs a TVMValue based on its type.
98 *
99 * \param tcode the type_code of the value stored in TVMValue.
100 * \param value is the TVMValue to be logged.
101 */
102 void LogTVMValue(int tcode, TVMValue value);
103
104 /*!
105 * \brief this function output the log to the console.
106 */
107 void OutputLog();
108
109 private:
110 std::stringstream os_;
111};
112
113/*!
114 * \brief A wrapper for a MinRPCReturns object, that also logs the responses.
115 *
116 * \param next underlying MinRPCReturns that generates the responses.
117 */
118class MinRPCReturnsWithLog : public MinRPCReturnInterface {
119 public:
120 /*!
121 * \brief Constructor.
122 * \param io The IO handler.
123 */
124 MinRPCReturnsWithLog(MinRPCReturnInterface* next, Logger* logger)
125 : next_(next), logger_(logger) {}
126
127 ~MinRPCReturnsWithLog() {}
128
129 void ReturnVoid();
130
131 void ReturnHandle(void* handle);
132
133 void ReturnException(const char* msg);
134
135 void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args);
136
137 void ReturnCopyFromRemote(uint8_t* data_ptr, uint64_t num_bytes);
138
139 void ReturnLastTVMError();
140
141 void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
142
143 /*!
144 * \brief this function logs a list of TVMValues, and registers handle_name when needed.
145 *
146 * \param values is the list of TVMValues.
147 * \param tcodes is the list type_code of the TVMValues.
148 * \param num_args is the number of items in the list.
149 */
150 void ProcessValues(const TVMValue* values, const int* tcodes, int num_args);
151
152 /*!
153 * \brief this function is called when a new command is executed.
154 * It clears the handle_name_ and records the command code.
155 *
156 * \param code the RPC command code.
157 */
158 void ResetHandleName(RPCCode code);
159
160 /*!
161 * \brief appends name to the handle_name_.
162 *
163 * \param name handle name.
164 */
165 void UpdateHandleName(const char* name);
166
167 /*!
168 * \brief get the stored handle description.
169 *
170 * \param handle the handle to get the description for.
171 */
172 void GetHandleName(void* handle);
173
174 /*!
175 * \brief remove the handle description from handle_descriptions_.
176 *
177 * \param handle the handle to remove the description for.
178 */
179 void ReleaseHandleName(void* handle);
180
181 private:
182 /*!
183 * \brief add the handle description to handle_descriptions_.
184 *
185 * \param handle the handle to add the description for.
186 */
187 void RegisterHandleName(void* handle);
188
189 MinRPCReturnInterface* next_;
190 std::string handle_name_;
191 std::unordered_map<void*, std::string> handle_descriptions_;
192 RPCCode code_;
193 Logger* logger_;
194};
195
196/*!
197 * \brief A wrapper for a MinRPCExecute object, that also logs the responses.
198 *
199 * \param next: underlying MinRPCExecute that processes the packets.
200 */
201class MinRPCExecuteWithLog : public MinRPCExecInterface {
202 public:
203 MinRPCExecuteWithLog(MinRPCExecInterface* next, Logger* logger) : next_(next), logger_(logger) {
204 ret_handler_ = reinterpret_cast<MinRPCReturnsWithLog*>(next_->GetReturnInterface());
205 }
206
207 ~MinRPCExecuteWithLog() {}
208
209 void InitServer(int num_args);
210
211 void NormalCallFunc(uint64_t call_handle, TVMValue* values, int* tcodes, int num_args);
212
213 void CopyFromRemote(DLTensor* arr, uint64_t num_bytes, uint8_t* temp_data);
214
215 int CopyToRemote(DLTensor* arr, uint64_t _num_bytes, uint8_t* _data_ptr);
216
217 void SysCallFunc(RPCCode code, TVMValue* values, int* tcodes, int num_args);
218
219 void ThrowError(RPCServerStatus code, RPCCode info = RPCCode::kNone);
220
221 MinRPCReturnInterface* GetReturnInterface() { return next_->GetReturnInterface(); }
222
223 private:
224 /*!
225 * \brief this function logs a list of TVMValues, and updates handle_name when needed.
226 *
227 * \param values is the list of TVMValues.
228 * \param tcodes is the list type_code of the TVMValues.
229 * \param num_args is the number of items in the list.
230 */
231 void ProcessValues(TVMValue* values, int* tcodes, int num_args);
232
233 /*!
234 * \brief this function is called when a new command is executed.
235 *
236 * \param code the RPC command code.
237 */
238 void SetRPCCode(RPCCode code);
239
240 MinRPCExecInterface* next_;
241 MinRPCReturnsWithLog* ret_handler_;
242 Logger* logger_;
243};
244
245/*!
246 * \brief A No-operation MinRPCReturns used within the MinRPCSniffer
247 *
248 * \tparam TIOHandler* IO provider to provide io handling.
249 */
250template <typename TIOHandler>
251class MinRPCReturnsNoOp : public MinRPCReturnInterface {
252 public:
253 /*!
254 * \brief Constructor.
255 * \param io The IO handler.
256 */
257 explicit MinRPCReturnsNoOp(TIOHandler* io) : io_(io) {}
258 ~MinRPCReturnsNoOp() {}
259 void ReturnVoid() {}
260 void ReturnHandle(void* handle) {}
261 void ReturnException(const char* msg) {}
262 void ReturnPackedSeq(const TVMValue* arg_values, const int* type_codes, int num_args) {}
263 void ReturnCopyFromRemote(uint8_t* data_ptr, uint64_t num_bytes) {}
264 void ReturnLastTVMError() {}
265 void ThrowError(RPCServerStatus code, RPCCode info) {}
266
267 private:
268 TIOHandler* io_;
269};
270
271/*!
272 * \brief A No-operation MinRPCExecute used within the MinRPCSniffer
273 *
274 * \tparam ReturnInterface* ReturnInterface pointer to generate and send the responses.
275
276 */
277class MinRPCExecuteNoOp : public MinRPCExecInterface {
278 public:
279 explicit MinRPCExecuteNoOp(MinRPCReturnInterface* ret_handler) : ret_handler_(ret_handler) {}
280 ~MinRPCExecuteNoOp() {}
281 void InitServer(int _num_args) {}
282 void NormalCallFunc(uint64_t call_handle, TVMValue* values, int* tcodes, int num_args) {}
283 void CopyFromRemote(DLTensor* arr, uint64_t num_bytes, uint8_t* temp_data) {}
284 int CopyToRemote(DLTensor* arr, uint64_t num_bytes, uint8_t* data_ptr) { return 1; }
285 void SysCallFunc(RPCCode code, TVMValue* values, int* tcodes, int num_args) {}
286 void ThrowError(RPCServerStatus code, RPCCode info) {}
287 MinRPCReturnInterface* GetReturnInterface() { return ret_handler_; }
288
289 private:
290 MinRPCReturnInterface* ret_handler_;
291};
292
293} // namespace runtime
294} // namespace tvm
295
296#endif // TVM_RUNTIME_MINRPC_MINRPC_LOGGER_H_"
297