scc 2026.07
SystemC components library
tcp4tlm_bridge.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_BRIDGE_H_
18#define TLM_SCC_TCP4TLM_BRIDGE_H_
19
20#include "rigtorp/SPSCQueue.h"
21#include "scc/async_event.h"
22#include "scc/async_queue.h"
23#include "scc/peq.h"
24#include "tcp4tlm/client.h"
25#include "tcp4tlm/messages.h"
26#include "tcp4tlm/server.h"
27#include "tlm/scc/tlm_gp_shared.h"
28#include "tlm/scc/tlm_mm.h"
29#include <atomic>
30#include <boost/asio.hpp>
31#include <cci_configuration>
32#include <scc/report.h>
33#include <scc/utilities.h>
34#include <systemc>
35#include <tlm>
36#include <tlm_utils/simple_initiator_socket.h>
37#include <tlm_utils/simple_target_socket.h>
38#include <tlm_utils/tlm_quantumkeeper.h>
39
40namespace scc {
41
69struct tcp4tlm_bridge : public sc_core::sc_module,
70 protected tcp4tlm::server<tcp4tlm::request_message, tcp4tlm::response_message>,
71 protected tcp4tlm::client<tcp4tlm::request_message, tcp4tlm::response_message> {
72 SC_HAS_PROCESS(tcp4tlm_bridge);
73
78 cci::cci_param<bool> is_connection_server{"is_connection_server", false};
79 cci::cci_param<std::string> other_host_name{"other_host_name", ""};
80 cci::cci_param<unsigned> other_host_port{"other_host_port", 0};
81 cci::cci_param<unsigned> this_host_port{"this_host_port", 32000u};
82 cci::cci_param<bool> wall_time_simulation_speed{"wall_time_simulation_speed", false};
83 cci::cci_param<bool> write_no_response{"write_no_response", false};
84 cci::cci_param<bool> no_systemc_sync{"no_systemc_sync", false};
85
86 tlm_utils::simple_target_socket<tcp4tlm_bridge, ::scc::LT> tsckt;
87
88 tlm_utils::simple_initiator_socket<tcp4tlm_bridge, ::scc::LT> isckt;
89
90 sc_core::sc_vector<sc_core::sc_out<bool>> signals{"signals"};
91
92 tcp4tlm_bridge(sc_core::sc_module_name name, size_t no_of_ports = 0);
93
94 virtual ~tcp4tlm_bridge();
95
96 typedef tcp4tlm::connection<tcp4tlm::response_message, tcp4tlm::request_message> connection_type;
97 typedef std::shared_ptr<connection_type> con_ptr;
98
99 void server_send_completed(con_ptr& con, bool established = false) override {
100 if(established) {
101 con->async_read();
102 }
103 }
104
105 void server_receive_completed(con_ptr& con, const tcp4tlm::request_message* const result) override;
106
107 void start_server() {
108 using namespace std::chrono_literals;
109 server::start_server(this_host_port.get_value());
110 }
111
112 void wait4connection() {
113 using namespace std::chrono_literals;
114 // wait until con_ext becomes true. To mitigate lost notifications the wait_for wuns in a loop
115 std::unique_lock<std::mutex> lock(con_est_mtx);
116 while(!con_est.load())
117 con_est_sig.wait_for(lock, 100ms, [this]() { return con_est.load(); });
118 }
119
120 bool is_connection_established() { return con_est; }
121
122 void end_connection();
123
124 sc_core::sc_event const& get_shutdown_event() const { return shutdown_evt; }
125
126protected:
127 using callback_task = std::packaged_task<bool(void)>;
128 struct timed_task {
129 callback_task t;
130 sc_core::sc_time timepoint;
131 };
133 scc::peq<callback_task> timed_task_que;
134 std::mutex con_est_mtx; //, gp_mtx, sync_mtx;
135 std::condition_variable con_est_sig;
136 std::atomic<bool> con_est{false};
137 sc_core::sc_event shutdown_evt;
139 unsigned long long sync;
140 void btransport_cb(tlm::tlm_generic_payload&, sc_core::sc_time&);
141 unsigned transport_dbg_cb(tlm::tlm_generic_payload&);
142 virtual void do_access(tlm::tlm_generic_payload& gp, sc_core::sc_time& delay, bool debug = false);
143 void timing_thread();
144 void process_task_que();
145 void process_timed_task_que();
146 void end_of_elaboration() override;
147 void start_of_simulation() override;
148 void end_of_simulation() override;
149 std::shared_ptr<tcp4tlm::response_message> resp_msg;
150 tlm_utils::tlm_quantumkeeper quantumkeeper;
152
153private:
154 tlm::scc::tlm_gp_shared_ptr init_gp(const tcp4tlm::BusOpMsg* const msg);
155#ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS
156 tcp4tlm::request_message get_notify_endpoint_msg(boost::asio::local::stream_protocol::endpoint& ep) {
157 return tcp4tlm::make_notify_endpoint_msg(ep.path(), 0);
158 };
159#endif
160 tcp4tlm::request_message get_notify_endpoint_msg(boost::asio::ip::tcp::endpoint& ep) {
161 boost::asio::ip::address addr = ep.address();
162 return tcp4tlm::make_notify_endpoint_msg(addr.is_unspecified() ? boost::asio::ip::host_name() : addr.to_string(), ep.port());
163 }
164#ifdef GENERATE_STATISTICS
165 std::vector<unsigned long> rtto, txt, rxt;
166
167public:
168 struct statistics {
169 std::vector<unsigned long> histogram;
170 unsigned long min, max;
171 unsigned long long sum;
172 tlm_genip::addr_decoder_if& indexer;
173 unsigned long count;
174 bool print_histogram;
175 statistics(tlm_genip::addr_decoder_if& indexer_, size_t hsize, unsigned long initval)
176 : histogram(hsize, 0)
177 , min(initval)
178 , max(initval)
179 , sum(initval)
180 , indexer(indexer_)
181 , count(1)
182 , print_histogram(false) {}
183 void updateStat(unsigned long rt);
184 };
185#endif
186};
187
188#ifdef GENERATE_STATISTICS
189inline ostream& operator<<(ostream& os, const tcp4tlm_bridge::statistics& stat) {
190 if(stat.print_histogram)
191 for(size_t i = 0; i < stat.histogram.size() - 1; ++i)
192 os << "\t[" << stat.indexer.getBaseAddr(i) / 1000 << "us;" << stat.indexer.getBaseAddr(i + 1) / 1000 << "us)\t-> "
193 << stat.histogram[i] << endl;
194 else
195 os << stat.min << "," << stat.sum / stat.count << "," << stat.max;
196 return os;
197}
198#endif
199
200inline void tcp4tlm_bridge::end_connection() {
201 SCCINFO(SCMOD) << "Sending shutdown message";
202 if(is_remote_connected()) {
203 auto smsg = tcp4tlm::make_sync_msg(sc_core::sc_time_stamp().value());
204 client_connection().write_data(smsg);
205 auto msg = tcp4tlm::make_notify_shutdown_msg();
206 client_connection().write_data(msg);
207 }
208}
209
210} // namespace scc
211
212#endif // TLM_SCC_TCP4TLM_BRIDGE_H_
SCC TLM utilities.
std::ostream & operator<<(std::ostream &os, log const &val)
output the textual representation of the log level
Definition report.h:133
priority event queue
Definition peq.h:42
cci::cci_param< bool > is_connection_server
a tlm memory manager
Definition tlm_mm.h:330