scc 2026.07
SystemC components library
messages.h
1/*******************************************************************************
2 * Copyright 2026 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17#ifndef TLM_SCC_TCP4TLM_MESSAGES_H_
18#define TLM_SCC_TCP4TLM_MESSAGES_H_
19
20#include "messages_generated.h"
21#include <atomic>
22#include <cstdint>
23#include <string>
24#include <utility>
25#include <vector>
26
27namespace scc {
28namespace tcp4tlm {
29
30template <typename Root> class message_buffer {
31public:
32 message_buffer() = default;
33
34 explicit message_buffer(std::vector<uint8_t> storage)
35 : storage_(std::move(storage))
36 , root_(nullptr) {
37 refresh_root();
38 }
39
40 const Root* root() const { return root_; }
41 const Root* operator->() const { return root_; }
42 explicit operator bool() const { return root_ != nullptr; }
43
44 const uint8_t* data() const { return storage_.empty() ? nullptr : storage_.data(); }
45 std::size_t size() const { return storage_.size(); }
46
47 static bool verify(const uint8_t* data, std::size_t size) {
48 if(data == nullptr || size == 0) {
49 return false;
50 }
51 flatbuffers::Verifier verifier(data, size);
52 return verifier.VerifyBuffer<Root>(nullptr);
53 }
54
55private:
56 void refresh_root() { root_ = verify(data(), size()) ? flatbuffers::GetRoot<Root>(data()) : nullptr; }
57
58 std::vector<uint8_t> storage_;
59 const Root* root_;
60};
61
62using request_message = message_buffer<RequestEnvelope>;
63using response_message = message_buffer<ResponseEnvelope>;
64using response_status = ResponseStatus;
65using bus_access_type = BusAccessType;
66
67constexpr response_status ok = ResponseStatus_OK;
68constexpr response_status accepted = ResponseStatus_ACCEPTED;
69constexpr response_status delayed = ResponseStatus_DELAYED;
70constexpr response_status declined = ResponseStatus_DECLINED;
71constexpr response_status failure = ResponseStatus_FAILURE;
72
73constexpr bus_access_type normal_acc = BusAccessType_NORMAL_ACC;
74constexpr bus_access_type debug_acc = BusAccessType_DEBUG_ACC;
75
76inline const char* get_status_str(response_status status) { return EnumNameResponseStatus(status); }
77
78inline uint32_t next_request_id() {
79 static std::atomic<uint32_t> id_counter{0};
80 return id_counter++;
81}
82
83template <typename Root> inline message_buffer<Root> make_message(flatbuffers::FlatBufferBuilder& builder) {
84 auto detached = builder.Release();
85 return message_buffer<Root>(std::vector<uint8_t>(detached.data(), detached.data() + detached.size()));
86}
87
88inline request_message make_request(RequestPayload payload_type, flatbuffers::Offset<void> payload,
89 flatbuffers::FlatBufferBuilder& builder) {
90 auto envelope = CreateRequestEnvelope(builder, payload_type, payload);
91 builder.Finish(envelope);
92 return make_message<RequestEnvelope>(builder);
93}
94
95inline response_message make_response_message(ResponsePayload payload_type, flatbuffers::Offset<void> payload,
96 flatbuffers::FlatBufferBuilder& builder) {
97 auto envelope = CreateResponseEnvelope(builder, payload_type, payload);
98 builder.Finish(envelope);
99 return make_message<ResponseEnvelope>(builder);
100}
101
102inline request_message make_notify_endpoint_msg(const std::string& hostname, uint16_t port, uint32_t id = next_request_id()) {
103 flatbuffers::FlatBufferBuilder builder;
104 auto payload = CreateNotifyEndpointMsgDirect(builder, id, hostname.c_str(), port);
105 return make_request(RequestPayload_NotifyEndpointMsg, payload.Union(), builder);
106}
107
108inline request_message make_notify_shutdown_msg(uint32_t id = next_request_id()) {
109 flatbuffers::FlatBufferBuilder builder;
110 auto payload = CreateNotifyShutdownMsg(builder, id);
111 return make_request(RequestPayload_NotifyShutdownMsg, payload.Union(), builder);
112}
113
114inline request_message make_sync_msg(uint64_t time_stamp, uint32_t id = next_request_id()) {
115 flatbuffers::FlatBufferBuilder builder;
116 auto payload = CreateSyncMsg(builder, id, time_stamp);
117 return make_request(RequestPayload_SyncMsg, payload.Union(), builder);
118}
119
120inline request_message make_bus_op_msg(uint64_t time_stamp, uint64_t time_offset, bus_access_type type, uint32_t index, uint64_t address,
121 uint32_t size, bool no_response, const std::vector<uint8_t>& data,
122 const std::vector<uint8_t>& byte_enable, uint32_t id = next_request_id()) {
123 flatbuffers::FlatBufferBuilder builder;
124 auto payload = CreateBusOpMsgDirect(builder, id, time_stamp, time_offset, type, index, address, size, no_response, &data, &byte_enable);
125 return make_request(RequestPayload_BusOpMsg, payload.Union(), builder);
126}
127
128inline request_message make_sig_op_msg(uint64_t time_stamp, uint32_t index, uint8_t value, uint32_t id = next_request_id()) {
129 flatbuffers::FlatBufferBuilder builder;
130 auto payload = CreateSigOpMsg(builder, id, time_stamp, index, value);
131 return make_request(RequestPayload_SigOpMsg, payload.Union(), builder);
132}
133
134inline request_message make_log_msg(const std::string& msg, uint32_t id = next_request_id()) {
135 flatbuffers::FlatBufferBuilder builder;
136 auto payload = CreateLogMsgDirect(builder, id, msg.c_str());
137 return make_request(RequestPayload_LogMsg, payload.Union(), builder);
138}
139
140inline uint32_t get_request_id(const RequestEnvelope* req) {
141 if(req == nullptr) {
142 return 0;
143 }
144 switch(req->payload_type()) {
145 case RequestPayload_NotifyEndpointMsg:
146 return req->payload_as_NotifyEndpointMsg()->id();
147 case RequestPayload_NotifyShutdownMsg:
148 return req->payload_as_NotifyShutdownMsg()->id();
149 case RequestPayload_SyncMsg:
150 return req->payload_as_SyncMsg()->id();
151 case RequestPayload_BusOpMsg:
152 return req->payload_as_BusOpMsg()->id();
153 case RequestPayload_SigOpMsg:
154 return req->payload_as_SigOpMsg()->id();
155 case RequestPayload_LogMsg:
156 return req->payload_as_LogMsg()->id();
157 default:
158 return 0;
159 }
160}
161
162inline response_status get_status(const ResponseEnvelope* resp) {
163 if(resp == nullptr) {
164 return failure;
165 }
166 switch(resp->payload_type()) {
167 case ResponsePayload_ResponseMsg:
168 return resp->payload_as_ResponseMsg()->status();
169 case ResponsePayload_BusDataMsg:
170 return resp->payload_as_BusDataMsg()->status();
171 default:
172 return failure;
173 }
174}
175
176inline uint32_t get_req_id(const ResponseEnvelope* resp) {
177 if(resp == nullptr) {
178 return 0;
179 }
180 switch(resp->payload_type()) {
181 case ResponsePayload_ResponseMsg:
182 return resp->payload_as_ResponseMsg()->req_id();
183 case ResponsePayload_BusDataMsg:
184 return resp->payload_as_BusDataMsg()->req_id();
185 default:
186 return 0;
187 }
188}
189
190inline bool belongs_to(const ResponseEnvelope* resp, const RequestEnvelope* req) { return get_req_id(resp) == get_request_id(req); }
191
192inline response_message make_response(uint32_t req_id, response_status status = ok) {
193 flatbuffers::FlatBufferBuilder builder;
194 auto payload = CreateResponseMsg(builder, status, req_id);
195 return make_response_message(ResponsePayload_ResponseMsg, payload.Union(), builder);
196}
197
198inline response_message make_response(const RequestEnvelope* req, response_status status = ok) {
199 return make_response(get_request_id(req), status);
200}
201
202inline response_message make_bus_data_msg(uint32_t req_id, const std::vector<uint8_t>& data, response_status status = ok) {
203 flatbuffers::FlatBufferBuilder builder;
204 auto payload = CreateBusDataMsgDirect(builder, status, req_id, &data);
205 return make_response_message(ResponsePayload_BusDataMsg, payload.Union(), builder);
206}
207
208inline response_message make_bus_data_msg(const RequestEnvelope* req, const std::vector<uint8_t>& data, response_status status = ok) {
209 return make_bus_data_msg(get_request_id(req), data, status);
210}
211
212} // namespace tcp4tlm
213} // namespace scc
214
215#endif // TLM_SCC_TCP_DETAIL_MESSAGES_H_
SCC TLM utilities.