71 static std::string txn_str(tlm::tlm_generic_payload&
trans)
73 std::stringstream
info;
75 const char* cmd =
"unknown";
76 switch (
trans.get_command()) {
77 case tlm::TLM_IGNORE_COMMAND:
80 case tlm::TLM_WRITE_COMMAND:
83 case tlm::TLM_READ_COMMAND:
88 info <<
" " << cmd <<
" to address "
89 <<
"0x" << std::hex <<
trans.get_address();
91 info <<
" len:" <<
trans.get_data_length();
92 unsigned char*
ptr =
trans.get_data_ptr();
93 info <<
" returned with data 0x";
94 for (
int i =
trans.get_data_length();
i;
i--) {
95 info << std::setw(2) << std::setfill(
'0') << std::hex << (
unsigned int)(
ptr[
i - 1]);
97 info <<
" status:" <<
trans.get_response_status() <<
" ";
98 if (
trans.is_dmi_allowed())
info <<
" DMI OK ";
99 for (
int i = 0;
i < tlm::max_num_extensions();
i++) {
100 if (
trans.get_extension(
i)) {
101 info <<
" extn " <<
i;
107 using str_pairs = std::vector<std::pair<std::string, std::string>>;
111 std::map<uint64_t, tlm::tlm_dmi> m_dmi_cache;
112 tlm::tlm_dmi* in_cache(
uint64_t address)
114 if (m_dmi_cache.size() > 0) {
115 auto it = m_dmi_cache.upper_bound(address);
116 if (
it != m_dmi_cache.begin()) {
119 return &(
it->second);
127 auto it = m_dmi_cache.upper_bound(start);
129 if (
it != m_dmi_cache.begin()) {
137 while (
it != m_dmi_cache.end()) {
138 tlm::tlm_dmi& r =
it->second;
140 if (r.get_start_address() > end) {
145 if (r.get_end_address() < start) {
150 it = m_dmi_cache.erase(
it);
156 std::string m_shmem_fn;
163 double m_dmi_read_latency;
164 double m_dmi_write_latency;
166 MSGPACK_DEFINE_ARRAY(m_shmem_fn, m_shmem_size, m_shmem_offset, m_dmi_start_address, m_dmi_end_address,
167 m_dmi_access, m_dmi_read_latency, m_dmi_write_latency);
171 m_shmem_fn =
shm->m_memid;
172 m_shmem_size =
shm->m_size;
174 m_dmi_start_address =
other.get_start_address();
175 m_dmi_end_address =
other.get_end_address();
176 m_dmi_access =
other.get_granted_access();
177 m_dmi_read_latency =
other.get_read_latency().to_seconds();
178 m_dmi_write_latency =
other.get_write_latency().to_seconds();
181 void to_tlm(tlm::tlm_dmi&
other)
183 if (m_shmem_size == 0)
return;
184 other.set_dmi_ptr(m_shmem_offset + MemoryServices::get().map_mem_join(m_shmem_fn.c_str(), m_shmem_size));
185 other.set_start_address(m_dmi_start_address);
186 other.set_end_address(m_dmi_end_address);
187 other.set_granted_access((tlm::tlm_dmi::dmi_access_e)m_dmi_access);
188 other.set_read_latency(sc_core::sc_time(m_dmi_read_latency, sc_core::SC_SEC));
189 other.set_write_latency(sc_core::sc_time(m_dmi_write_latency, sc_core::SC_SEC));
193 struct tlm_generic_payload_rpc {
194 sc_dt::uint64 m_address;
196 unsigned int m_length;
197 int m_response_status;
199 unsigned int m_byte_enable_length;
200 unsigned int m_streaming_width;
204 double m_quantum_time;
206 std::vector<unsigned char> m_data;
207 std::vector<unsigned char> m_byte_enable;
209 MSGPACK_DEFINE_ARRAY(m_address, m_command, m_length, m_response_status, m_dmi, m_byte_enable_length,
210 m_streaming_width, m_gp_option, m_sc_time, m_quantum_time, m_data, m_byte_enable);
212 void from_tlm(tlm::tlm_generic_payload&
other)
214 m_command =
other.get_command();
215 m_address =
other.get_address();
216 m_length =
other.get_data_length();
217 m_response_status =
other.get_response_status();
218 m_byte_enable_length =
other.get_byte_enable_length();
219 m_streaming_width =
other.get_streaming_width();
220 m_gp_option =
other.get_gp_option();
221 m_dmi =
other.is_dmi_allowed();
224 m_data.resize(m_length);
232 m_byte_enable.resize(m_byte_enable_length);
235 m_byte_enable_length = 0;
236 m_byte_enable.clear();
239 void deep_copy_to_tlm(tlm::tlm_generic_payload&
other)
241 other.set_command((tlm::tlm_command)(m_command));
242 other.set_address(m_address);
243 other.set_data_length(m_length);
244 other.set_response_status((tlm::tlm_response_status)(m_response_status));
245 other.set_byte_enable_length(m_byte_enable_length);
246 other.set_streaming_width(m_streaming_width);
247 other.set_gp_option((tlm::tlm_gp_option)(m_gp_option));
248 other.set_dmi_allowed(m_dmi);
250 other.set_data_ptr(
nullptr);
252 other.set_data_ptr(
reinterpret_cast<unsigned char*
>(m_data.data()));
254 if (!m_byte_enable_length) {
255 other.set_byte_enable_ptr(
nullptr);
257 other.set_byte_enable_ptr(
reinterpret_cast<unsigned char*
>(m_byte_enable.data()));
261 void update_to_tlm(tlm::tlm_generic_payload&
other)
263 tlm::tlm_generic_payload
tmp;
265 tmp.set_data_ptr(
nullptr);
267 tmp.set_data_ptr(
reinterpret_cast<unsigned char*
>(m_data.data()));
270 if (!m_byte_enable_length) {
271 other.set_byte_enable_ptr(
nullptr);
273 tmp.set_byte_enable_ptr(
reinterpret_cast<unsigned char*
>(m_byte_enable.data()));
275 tmp.set_data_length(m_length);
276 tmp.set_byte_enable_length(m_byte_enable_length);
277 tmp.set_response_status((tlm::tlm_response_status)m_response_status);
278 tmp.set_dmi_allowed(m_dmi);
279 other.update_original_from(
tmp, m_byte_enable_length > 0);
283 cci::cci_broker_handle m_broker;
285 std::mutex m_cci_db_mut;
287 class initiator_socket_spying
288 :
public tlm_utils::simple_initiator_socket_b<MOD, BUSWIDTH, tlm::tlm_base_protocol_types,
289 sc_core::SC_ZERO_OR_MORE_BOUND>
291 using socket_type = tlm_utils::simple_initiator_socket_b<
MOD,
BUSWIDTH, tlm::tlm_base_protocol_types,
292 sc_core::SC_ZERO_OR_MORE_BOUND>;
293 using typename socket_type::base_target_socket_type;
296 const std::function<
void(std::string)> register_cb;
299 initiator_socket_spying(
const char* name,
const std::function<
void(std::string)>&
f)
300 : socket_type::simple_initiator_socket_b(name), register_cb(
f)
306 socket_type::bind(socket);
307 register_cb(socket.get_base_export().name());
311 void bind(tlm::tlm_initiator_socket<BUSWIDTH>& socket)
313 socket_type::bind(socket);
314 register_cb(socket.get_base_port().name());
319 std::string nameFromSocket(std::string s) {
return s; }
321 void remote_register_boundto(std::string s) {
SCP_DEBUG(()) <<
"Binding: " << s; }
329 using tlm_target_socket = tlm_utils::simple_target_socket_tagged_b<
MOD,
BUSWIDTH, tlm::tlm_base_protocol_types,
330 sc_core::SC_ZERO_OR_MORE_BOUND>;
332 sc_core::sc_vector<tlm_target_socket> target_sockets;
333 sc_core::sc_vector<initiator_socket_spying> initiator_sockets;
335 sc_core::sc_vector<InitiatorSignalSocket<bool>> initiator_signal_sockets;
336 sc_core::sc_vector<TargetSignalSocket<bool>> target_signal_sockets;
338 cci::cci_param<int> p_cport;
339 cci::cci_param<int> p_sport;
340 cci::cci_param<std::string> p_exec_path;
342 cci::cci_param<std::string> p_sync_policy;
343 cci::cci_param<uint32_t> p_tlm_initiator_ports_num;
344 cci::cci_param<uint32_t> p_tlm_target_ports_num;
345 cci::cci_param<uint32_t> p_initiator_signals_num;
346 cci::cci_param<uint32_t> p_target_signals_num;
349 rpc::client* client =
nullptr;
350 rpc::server* server =
nullptr;
353 std::condition_variable is_client_connected;
354 std::condition_variable is_sc_status_set;
355 std::mutex client_conncted_mut;
356 std::mutex sc_status_mut;
357 std::mutex stop_mutex;
358 std::atomic_bool cancel_waiting;
359 std::thread::id sc_tid;
360 std::queue<std::pair<int, bool>> sig_queue;
361 std::mutex sig_queue_mut;
362 std::vector<const char*> m_remote_args;
363 sc_core::sc_status m_remote_status =
static_cast<sc_core::sc_status
>(0);
365 int targets_bound = 0;
375 std::queue<std::function<
void()>> notifiers;
376 std::thread notifier_thread;
377 std::atomic_bool is_stopped;
378 std::atomic_bool is_started;
381 std::vector<gs::async_event> data_ready_events;
382 std::vector<sc_core::sc_event> port_available_events;
383 std::vector<bool> is_port_busy;
384 std::condition_variable is_rpc_execed;
385 std::mutex start_stop_mutex;
386 std::mutex rpc_execed_mut;
396 while (!is_stopped) {
397 std::unique_lock<std::mutex>
ul(rpc_execed_mut);
398 is_rpc_execed.wait_for(
ul, std::chrono::milliseconds(RPC_TIMEOUT),
399 [
this]() {
return (!notifiers.empty() || is_stopped); });
400 while (!notifiers.empty()) {
411 , data_ready_events(
ev_num)
412 , port_available_events(
ev_num)
413 , is_port_busy(
ev_num,
false)
421 std::lock_guard<std::mutex>
start_lg(start_stop_mutex);
422 if (is_started)
return;
426 notifier_thread = std::thread(&trans_waiter::notifier_task,
this);
432 std::lock_guard<std::mutex>
stop_lg(start_stop_mutex);
433 if (is_stopped || !is_started)
return;
437 std::lock_guard<std::mutex>
lg(rpc_execed_mut);
438 is_rpc_execed.notify_one();
441 if (notifier_thread.joinable()) notifier_thread.join();
444 ~trans_waiter() { stop(); }
446 void enqueue_notifier(std::function<
void()> notifier) { notifiers.push(notifier); }
449 std::unique_ptr<trans_waiter> btspt_waiter;
451 template <
typename...
Args>
452 std::future<RPCLIB_MSGPACK::object_handle> do_rpc_async_call(std::string
const&
func_name,
Args... args)
457 std::future<RPCLIB_MSGPACK::object_handle>
ret;
459 ret = client->async_call(
func_name, std::forward<Args>(args)...);
460 }
catch (
const std::future_error&
e) {
461 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_call() Connection with remote is closed: " <<
e.what();
464 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_call() Unknown error!";
470 template <
typename T>
471 T do_rpc_async_get(std::future<RPCLIB_MSGPACK::object_handle>
fut)
476 }
catch (
const std::future_error&
e) {
477 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_get() RPC future is corrupted: " <<
e.what();
480 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_get() Unknown error!";
486 template <
typename T>
487 T do_rpc_as(RPCLIB_MSGPACK::object_handle
handle)
493 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_as() RPC remote value is corrupted!";
499 template <
typename...
Args>
500 RPCLIB_MSGPACK::object_handle do_rpc_call(std::string
const&
func_name,
Args... args)
505 RPCLIB_MSGPACK::object_handle
ret;
507 ret = client->call(
func_name, std::forward<Args>(args)...);
510 catch (
const std::future_error&
e) {
511 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_call() Connection with remote is closed: " <<
e.what();
514 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_call() Unknown error!";
521 bool is_local_mode() {
return (m_container && m_is_local); }
523 void fw_b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
override
525 SCP_DEBUG(()) <<
"calling b_transport on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
526 initiator_sockets[id]->b_transport(
trans, delay);
527 SCP_DEBUG(()) <<
"return from b_transport on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
530 unsigned int fw_transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
override
532 SCP_DEBUG(()) <<
"calling transport_dbg on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
533 unsigned int ret = initiator_sockets[id]->transport_dbg(
trans);
534 SCP_DEBUG(()) <<
"return from transport_dbg on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
538 bool fw_get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
override
540 SCP_DEBUG(()) <<
"calling get_direct_mem_ptr on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
541 bool ret = initiator_sockets[id]->get_direct_mem_ptr(
trans, dmi_data);
542 SCP_DEBUG(()) <<
"return from get_direct_mem_ptr on initiator_socket_" <<
id <<
" "
543 <<
" RET: " << std::boolalpha <<
ret <<
" " << scp::scp_txn_tostring(
trans)
544 <<
" IS_READ_ALLOWED: " << std::boolalpha << dmi_data.is_read_allowed() <<
" "
545 <<
" IS_WRITE_ALLOWED: " << std::boolalpha << dmi_data.is_write_allowed();
549 void fw_invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
override
551 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
552 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
553 for (
int i = 0;
i < target_sockets.size();
i++) {
554 target_sockets[
i]->invalidate_direct_mem_ptr(start, end);
558 void fw_handle_signal(
int id,
bool value)
override
560 SCP_DEBUG(()) <<
"calling handle_signal on initiator_signal_socket_" <<
id <<
" value: " << std::boolalpha
562 initiator_signal_sockets[id]->write(value);
566 void b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
568 if (is_local_mode()) {
569 m_container->fw_b_transport(
id,
trans, delay);
573 while (btspt_waiter->is_port_busy[
id]) {
574 sc_core::wait(btspt_waiter->port_available_events[
id]);
576 btspt_waiter->is_port_busy[id] =
true;
578 tlm_generic_payload_rpc
t;
579 tlm_generic_payload_rpc r;
580 double time = sc_core::sc_time_stamp().to_seconds();
585 auto c = in_cache(
addr);
589 switch (
trans.get_command()) {
590 case tlm::TLM_IGNORE_COMMAND:
592 case tlm::TLM_WRITE_COMMAND:
595 case tlm::TLM_READ_COMMAND:
599 trans.set_dmi_allowed(
true);
600 trans.set_response_status(tlm::TLM_OK_RESPONSE);
606 t.m_quantum_time = delay.to_seconds();
607 t.m_sc_time = sc_core::sc_time_stamp().to_seconds();
614 if (std::this_thread::get_id() == sc_tid && sc_core::sc_get_status() >= sc_core::sc_status::SC_RUNNING &&
615 sc_core::sc_get_curr_process_kind() != sc_core::sc_curr_proc_kind::SC_NO_PROC_) {
617 <<
" SC current process kind = " << sc_core::sc_get_curr_process_kind();
618 btspt_waiter->start();
620 std::unique_lock<std::mutex>
ul(btspt_waiter->rpc_execed_mut);
621 btspt_waiter->enqueue_notifier([&]() {
623 btspt_waiter->data_ready_events[id].async_notify();
625 btspt_waiter->is_rpc_execed.notify_one();
628 <<
" SC current process kind = " << sc_core::sc_get_curr_process_kind();
629 if (sc_core::sc_get_curr_process_kind() != sc_core::sc_curr_proc_kind::SC_METHOD_PROC_) {
630 sc_core::wait(btspt_waiter->data_ready_events[
id]);
632 SCP_FATAL(()) << name() <<
" b_transport was called from the context of SC_METHOD!";
638 r.update_to_tlm(
trans);
639 delay = sc_core::sc_time(r.m_quantum_time, sc_core::SC_SEC);
640 sc_core::sc_time
other_time = sc_core::sc_time(r.m_sc_time, sc_core::SC_SEC);
641 btspt_waiter->is_port_busy[id] =
false;
642 btspt_waiter->port_available_events[id].notify(sc_core::SC_ZERO_TIME);
644 tlm_generic_payload_rpc b_transport_rpc(
int id, tlm_generic_payload_rpc
t)
646 tlm::tlm_generic_payload
trans;
647 t.deep_copy_to_tlm(
trans);
648 sc_core::sc_time delay = sc_core::sc_time(
t.m_quantum_time, sc_core::SC_SEC);
649 sc_core::sc_time
other_time = sc_core::sc_time(
t.m_sc_time, sc_core::SC_SEC);
651 m_sc.
run_on_sysc([&] { initiator_sockets[id]->b_transport(
trans, delay); });
653 t.m_quantum_time = delay.to_seconds();
658 unsigned int transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
660 if (is_local_mode()) {
661 return m_container->fw_transport_dbg(
id,
trans);
663 SCP_DEBUG(()) << name() <<
" ->remote debug tlm " << txn_str(
trans);
664 tlm_generic_payload_rpc
t;
665 tlm_generic_payload_rpc r;
669 r.update_to_tlm(
trans);
670 SCP_DEBUG(()) << name() <<
" <-remote debug tlm done " << txn_str(
trans);
672 return trans.get_response_status() == tlm::TLM_OK_RESPONSE ?
trans.get_data_length() : 0;
674 tlm_generic_payload_rpc transport_dbg_rpc(
int id, tlm_generic_payload_rpc
t)
676 tlm::tlm_generic_payload
trans;
677 t.deep_copy_to_tlm(
trans);
679 SCP_DEBUG(()) << name() <<
" remote-> debug tlm " << txn_str(
trans);
682 SCP_DEBUG(()) << name() <<
" remote<- debug tlm done " << txn_str(
trans);
684 if (!(
trans.get_data_length() ==
ret_len ||
trans.get_response_status() != tlm::TLM_OK_RESPONSE)) {
686 SCP_WARN(()) <<
"debug transaction not able to access required length of data.";
691 bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
693 if (is_local_mode()) {
694 return m_container->fw_get_direct_mem_ptr(
id,
trans, dmi_data);
697 SCP_DEBUG(()) <<
" " << name() <<
" get_direct_mem_ptr to address "
698 <<
"0x" << std::hex <<
trans.get_address();
701 c = in_cache(
trans.get_address());
704 return !(dmi_data.is_none_allowed());
707 tlm_generic_payload_rpc
t;
712 if (r.m_shmem_size == 0) {
713 SCP_DEBUG(()) << name() <<
"DMI OK, but no shared memory available?" <<
trans.get_address();
718 assert(m_dmi_cache.count(dmi_data.get_start_address()) == 0);
719 m_dmi_cache[dmi_data.get_start_address()] = dmi_data;
721 return !(dmi_data.is_none_allowed());
724 tlm_dmi_rpc get_direct_mem_ptr_rpc(
int id, tlm_generic_payload_rpc
t)
726 tlm::tlm_generic_payload
trans;
727 t.deep_copy_to_tlm(
trans);
729 SCP_DEBUG(()) <<
" " << name() <<
" get_direct_mem_ptr " << txn_str(
trans);
731 tlm::tlm_dmi dmi_data;
733 ret.m_shmem_size = 0;
734 if (initiator_sockets[
id]->get_direct_mem_ptr(
trans, dmi_data)) {
737 ret.from_tlm(dmi_data,
ext);
743 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
745 if (is_local_mode()) {
746 m_container->fw_invalidate_direct_mem_ptr(start, end);
748 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
749 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
750 do_rpc_async_call(
"dmi_inv", start, end);
752 void invalidate_direct_mem_ptr_rpc(sc_dt::uint64 start, sc_dt::uint64 end)
754 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
755 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
757 cache_clean(start, end);
759 for (
int i = 0;
i < target_sockets.size();
i++) {
760 target_sockets[
i]->invalidate_direct_mem_ptr(start, end);
767 bool is_self_param(
const std::string& parent,
const std::string&
parname,
const std::string& value)
770 "args",
"moduletype",
"initiator_socket",
"target_socket",
"initiator_signal_socket",
"target_signal_socket"
773 std::string search_str = parent +
"." + entry;
774 if (entry ==
"moduletype" && value ==
"\"RemotePass\"") search_str = entry;
775 return parname.find(search_str) != std::string::npos;
779 str_pairs get_cci_db()
781 std::string parent = std::string(name());
783 for (
auto p : m_broker.get_unconsumed_preset_values()) {
784 std::string name =
p.first;
785 std::string
k =
p.first;
786 if (
k.find(parent) == 0) {
787 if (is_self_param(parent,
k,
p.second.to_json()))
continue;
788 k =
k.substr(parent.length() + 1);
789 ret.push_back(std::make_pair(
"$" +
k,
p.second.to_json()));
791 m_broker.ignore_unconsumed_preset_values(
792 [name](
const std::pair<std::string, cci::cci_value>&
iv) ->
bool {
return iv.first == name; });
793 }
else if (
k.find(
'.') == std::string::npos) {
794 ret.push_back(std::make_pair(
k,
p.second.to_json()));
800 void set_cci_db(str_pairs
db)
802 std::string
modname = std::string(name());
803 std::string parent = std::string(
modname).substr(0,
modname.find_last_of(
"."));
807 if (
p.first[0] ==
'$') {
808 parname = parent +
"." +
p.first.substr(1);
809 }
else if (
p.first[0] ==
'@') {
816 handle.set_cci_value(cci::cci_value::from_json(
p.second));
818 m_broker.set_preset_cci_value(
parname, cci::cci_value::from_json(
p.second));
824 std::vector<std::string> get_extra_argv()
826 std::vector<std::string>
argv;
830 [
this](
const std::string&
arg) {
831 std::string arg_full_name = (std::string(name()) +
".remote_argv." + arg);
832 return gs::cci_get<std::string>(cci::cci_get_broker(), arg_full_name);
839 : sc_core::sc_module(
nm)
840 , m_broker(cci::cci_get_broker())
841 , initiator_sockets(
"initiator_socket")
842 , target_sockets(
"target_socket")
843 , initiator_signal_sockets(
"initiator_signal_socket")
844 , target_signal_sockets(
"target_signal_socket")
845 , p_cport(
"client_port", 0,
846 "The port that should be used to connect this client to the "
848 , p_sport(
"server_port", 0,
"The port that should be used to server on")
849 , p_exec_path(
"exec_path",
"",
850 "The path to the executable that should be started by "
853 , p_sync_policy(
"sync_policy",
"multithread-unconstrained",
"Sync policy for the remote")
854 , p_tlm_initiator_ports_num(
"tlm_initiator_ports_num", 0,
"number of tlm initiator ports")
855 , p_tlm_target_ports_num(
"tlm_target_ports_num", 0,
"number of tlm target ports")
856 , p_initiator_signals_num(
"initiator_signals_num", 0,
"number of initiator signals")
857 , p_target_signals_num(
"target_signals_num", 0,
"number of target signals")
858 , cancel_waiting(
false)
860 SigHandler::get().add_sig_handler(
SIGINT, SigHandler::Handler_CB::PASS);
861 SigHandler::get().register_on_exit_cb(std::string(name()) +
".gs::PassRPC::stop", [
this]() { stop(); });
862 sc_tid = std::this_thread::get_id();
865 if (is_local_mode()) {
866 SCP_DEBUG(()) <<
"Working in LOCAL mode!";
868 SCP_DEBUG(()) <<
getpid() <<
" IS THE RPC PID " << std::this_thread::get_id() <<
" is the thread ID";
870 server =
new rpc::server(p_sport);
871 server->suppress_exceptions(
true);
872 p_sport = server->port();
875 if (p_cport.get_value() == 0 &&
876 getenv((std::string(GS_Process_Server_Port) + std::to_string(
getpid())).
c_str())) {
878 std::string(
getenv((std::string(GS_Process_Server_Port) + std::to_string(
getpid())).
c_str())));
883 server->bind(
"reg", [&](
int port) {
885 assert(p_cport == 0 && client ==
nullptr);
887 if (!client) client =
new rpc::client(
"localhost", p_cport);
888 std::unique_lock<std::mutex>
ul(client_conncted_mut);
889 is_client_connected.notify_one();
892 do_rpc_async_call(
"sock_pair", pahandler.get_sockpair_fd0(), pahandler.get_sockpair_fd1());
898 server->bind(
"cci_db", [&](str_pairs
db) {
899 if (sc_core::sc_get_status() > sc_core::sc_status::SC_BEFORE_END_OF_ELABORATION) {
900 std::cerr <<
"Attempt to do cci_db() RPC after "
901 "sc_core::sc_status::SC_BEFORE_END_OF_ELABORATION"
905 std::lock_guard<std::mutex>
lg(m_cci_db_mut);
906 m_cci_db.insert(m_cci_db.end(),
db.begin(),
db.end());
910 server->bind(
"status", [&](
int s) {
911 SCP_DEBUG(()) <<
"SIMULATION STATE " << name() <<
" to status " << s;
912 assert(s > m_remote_status);
913 m_remote_status =
static_cast<sc_core::sc_status
>(s);
914 std::lock_guard<std::mutex>
lg(sc_status_mut);
915 is_sc_status_set.notify_one();
919 server->bind(
"b_tspt", [&](
int id, tlm_generic_payload_rpc
txn) {
921 return PassRPC::b_transport_rpc(
id,
txn);
922 }
catch (std::runtime_error
const&
e) {
923 std::cerr <<
"Main Error: '" <<
e.what() <<
"'\n";
925 }
catch (
const std::exception&
exc) {
926 std::cerr <<
"main Error: '" <<
exc.what() <<
"'\n";
929 std::cerr <<
"Unknown error (main.cc)!\n";
934 server->bind(
"dbg_tspt", [&](
int id, tlm_generic_payload_rpc
txn) {
936 return PassRPC::transport_dbg_rpc(
id,
txn);
940 return PassRPC::invalidate_direct_mem_ptr_rpc(start, end);
943 server->bind(
"dmi_req",
944 [&](
int id, tlm_generic_payload_rpc
txn) {
return PassRPC::get_direct_mem_ptr_rpc(
id,
txn); });
946 server->bind(
"exit", [&](
int i) {
949 rpc::this_session().post_exit();
958 server->bind(
"signal", [&](
int i,
bool v) {
959 if (sc_core::sc_get_status() < sc_core::sc_status::SC_START_OF_SIMULATION) {
960 std::lock_guard<std::mutex>
lg(sig_queue_mut);
961 sig_queue.push(std::make_pair(
i,
v));
964 m_sc.
run_on_sysc([&] { initiator_signal_sockets[
i]->write(
v); },
965 (sc_core::sc_get_status() < sc_core::sc_status::SC_RUNNING ?
false :
true));
972 std::cerr <<
"remote process (" <<
getpid() <<
") detected parent (" << pahandler.get_ppid()
973 <<
") exit!" << std::endl;
978 server->async_run(1);
981 SCP_INFO(()) <<
"Connecting client on port " << p_cport;
982 if (!client) client =
new rpc::client(
"localhost", p_cport);
987 btspt_waiter = std::make_unique<trans_waiter>(
"btspt_waiter", p_tlm_target_ports_num.get_value());
989 initiator_sockets.init(p_tlm_initiator_ports_num.get_value(), [
this](
const char*
n,
int i) {
990 return new initiator_socket_spying(n, [&](std::string s) -> void { remote_register_boundto(s); });
992 target_sockets.init(p_tlm_target_ports_num.get_value(),
993 [
this](
const char*
n,
int i) {
return new tlm_target_socket(
n); });
994 initiator_signal_sockets.init(p_initiator_signals_num.get_value(),
996 target_signal_sockets.init(p_target_signals_num.get_value(),
999 for (
int i = 0;
i < p_tlm_target_ports_num.get_value();
i++) {
1000 target_sockets[
i].register_b_transport(
this, &PassRPC::b_transport,
i);
1001 target_sockets[
i].register_transport_dbg(
this, &PassRPC::transport_dbg,
i);
1002 target_sockets[
i].register_get_direct_mem_ptr(
this, &PassRPC::get_direct_mem_ptr,
i);
1005 for (
int i = 0;
i < p_tlm_initiator_ports_num.get_value();
i++) {
1006 initiator_sockets[
i].register_invalidate_direct_mem_ptr(
this, &PassRPC::invalidate_direct_mem_ptr);
1009 for (
int i = 0;
i < p_target_signals_num.get_value();
i++) {
1010 target_signal_sockets[
i].register_value_changed_cb([&,
i](
bool value) {
1011 if (is_local_mode()) {
1012 m_container->fw_handle_signal(
i, value);
1015 do_rpc_async_call(
"signal",
i, value);
1019 if (!is_local_mode()) {
1020 if (!p_exec_path.get_value().empty()) {
1021 SCP_INFO(()) <<
"Forking remote " << p_exec_path.get_value();
1022 pahandler.init_peer_conn_checker();
1026 m_remote_args.reserve(
extra_args.size() + 2);
1027 m_remote_args.push_back(p_exec_path.get_value().c_str());
1029 [](
const std::string& s) { return s.c_str(); });
1030 m_remote_args.push_back(0);
1031 char val[DECIMAL_PORT_NUM_STR_LEN + 1];
1032 snprintf(
val, DECIMAL_PORT_NUM_STR_LEN + 1,
"%d", p_sport.get_value());
1033 m_child_pid =
fork();
1034 if (m_child_pid > 0) {
1035 pahandler.setup_parent_conn_checker();
1036 SigHandler::get().set_nosig_chld_stop();
1037 SigHandler::get().add_sig_handler(
SIGCHLD, SigHandler::Handler_CB::EXIT);
1038 }
else if (m_child_pid == 0) {
1039 char key[GS_Process_Server_Port_Len + DECIMAL_PID_T_STR_LEN + 1];
1040 snprintf(
key, GS_Process_Server_Port_Len + DECIMAL_PID_T_STR_LEN + 1,
"%s%d",
1041 GS_Process_Server_Port,
getpid());
1044 execv(p_exec_path.get_value().c_str(),
const_cast<char**
>(&m_remote_args[0]));
1046 SCP_FATAL(()) <<
"Unable to exec the remote child process, '" << p_exec_path.get_value()
1047 <<
"', error: " << std::strerror(
errno);
1049 SCP_FATAL(()) <<
"failed to fork remote process, error: " << std::strerror(
errno);
1054 std::unique_lock<std::mutex>
ul(client_conncted_mut);
1055 is_client_connected.wait(
ul, [&]() {
return (p_cport > 0 || cancel_waiting); });
1064 SCP_DEBUG(()) <<
"SIMULATION STATE send " << name() <<
" to status " << sc_core::sc_get_status();
1065 do_rpc_call(
"status",
static_cast<int>(sc_core::sc_get_status()));
1066 std::unique_lock<std::mutex>
ul(sc_status_mut);
1067 is_sc_status_set.wait(
ul, [&]() {
return (m_remote_status >= sc_core::sc_get_status() || cancel_waiting); });
1069 SCP_DEBUG(()) <<
"SIMULATION STATE synced " << name() <<
" to status " << sc_core::sc_get_status();
1072 void handle_before_sim_start_signals()
1074 std::lock_guard<std::mutex>
lg(sig_queue_mut);
1075 while (!sig_queue.empty()) {
1076 std::pair<int, bool>
sig = sig_queue.front();
1078 m_sc.run_on_sysc([&] { initiator_signal_sockets[
sig.first]->write(
sig.second); },
false);
1085 std::lock_guard<std::mutex>
lg(stop_mutex);
1086 if (cancel_waiting || is_local_mode())
return;
1087 cancel_waiting =
true;
1090 std::lock_guard<std::mutex>
cc_lg(client_conncted_mut);
1091 is_client_connected.notify_one();
1094 std::lock_guard<std::mutex>
scs_lg(sc_status_mut);
1095 is_sc_status_set.notify_one();
1097 btspt_waiter->stop();
1099 server->close_sessions();
1105 do_rpc_async_call(
"exit", 0);
1111 void stop_and_exit()
1117 void before_end_of_elaboration()
override
1119 if (is_local_mode())
return;
1121 std::lock_guard<std::mutex>
lg(m_cci_db_mut);
1122 set_cci_db(m_cci_db);
1125 void end_of_elaboration()
override
1127 if (is_local_mode())
return;
1131 void start_of_simulation()
override
1133 if (is_local_mode())
return;
1135 handle_before_sim_start_signals();
1139 PassRPC(
const PassRPC&) =
delete;
1142 SigHandler::get().deregister_on_exit_cb(std::string(name()) +
".gs::PassRPC::stop");
1143 if (is_local_mode())
return;
1147 m_dmi_cache.clear();
1151 void end_of_simulation()
override
1153 if (is_local_mode())
return;