165 static std::string txn_str(tlm::tlm_generic_payload&
trans)
167 std::stringstream
info;
169 const char* cmd =
"unknown";
170 switch (
trans.get_command()) {
171 case tlm::TLM_IGNORE_COMMAND:
174 case tlm::TLM_WRITE_COMMAND:
177 case tlm::TLM_READ_COMMAND:
182 info <<
" " << cmd <<
" to address "
183 <<
"0x" << std::hex <<
trans.get_address();
185 info <<
" len:" <<
trans.get_data_length();
186 unsigned char* ptr =
trans.get_data_ptr();
187 info <<
" returned with data 0x";
188 for (
int i =
trans.get_data_length();
i;
i--) {
189 info << std::setw(2) << std::setfill(
'0') << std::hex << (
unsigned int)(ptr[
i - 1]);
191 info <<
" status:" <<
trans.get_response_status() <<
" ";
192 if (
trans.is_dmi_allowed())
info <<
" DMI OK ";
193 for (
int i = 0;
i < tlm::max_num_extensions();
i++) {
194 if (
trans.get_extension(
i)) {
195 info <<
" extn " <<
i;
201 using str_pairs = std::vector<std::pair<std::string, std::string>>;
205 std::map<uint64_t, tlm::tlm_dmi> m_dmi_cache;
206 tlm::tlm_dmi* in_cache(
uint64_t address)
208 if (m_dmi_cache.size() > 0) {
209 auto it = m_dmi_cache.upper_bound(address);
210 if (
it != m_dmi_cache.begin()) {
213 return &(
it->second);
221 auto it = m_dmi_cache.upper_bound(start);
223 if (
it != m_dmi_cache.begin()) {
231 while (
it != m_dmi_cache.end()) {
232 tlm::tlm_dmi& r =
it->second;
234 if (r.get_start_address() > end) {
239 if (r.get_end_address() < start) {
244 it = m_dmi_cache.erase(
it);
250 std::string m_shmem_fn;
257 double m_dmi_read_latency;
258 double m_dmi_write_latency;
260 MSGPACK_DEFINE_ARRAY(m_shmem_fn, m_shmem_size, m_shmem_offset, m_dmi_start_address, m_dmi_end_address,
261 m_dmi_access, m_dmi_read_latency, m_dmi_write_latency);
265 m_shmem_fn =
shm->m_memid;
266 m_shmem_size =
shm->m_size;
268 m_dmi_start_address =
other.get_start_address();
269 m_dmi_end_address =
other.get_end_address();
270 m_dmi_access =
other.get_granted_access();
271 m_dmi_read_latency =
other.get_read_latency().to_seconds();
272 m_dmi_write_latency =
other.get_write_latency().to_seconds();
275 void to_tlm(tlm::tlm_dmi&
other)
277 if (m_shmem_size == 0)
return;
278 other.set_dmi_ptr(m_shmem_offset + MemoryServices::get().map_mem_join(m_shmem_fn, m_shmem_size));
279 other.set_start_address(m_dmi_start_address);
280 other.set_end_address(m_dmi_end_address);
281 other.set_granted_access((tlm::tlm_dmi::dmi_access_e)m_dmi_access);
282 other.set_read_latency(sc_core::sc_time(m_dmi_read_latency, sc_core::SC_SEC));
283 other.set_write_latency(sc_core::sc_time(m_dmi_write_latency, sc_core::SC_SEC));
287 struct tlm_generic_payload_rpc {
288 sc_dt::uint64 m_address;
290 unsigned int m_length;
291 int m_response_status;
293 unsigned int m_byte_enable_length;
294 unsigned int m_streaming_width;
298 double m_quantum_time;
300 std::vector<unsigned char> m_data;
301 std::vector<unsigned char> m_byte_enable;
303 MSGPACK_DEFINE_ARRAY(m_address, m_command, m_length, m_response_status, m_dmi, m_byte_enable_length,
304 m_streaming_width, m_gp_option, m_sc_time, m_quantum_time, m_data, m_byte_enable);
306 void from_tlm(tlm::tlm_generic_payload&
other)
308 m_command =
other.get_command();
309 m_address =
other.get_address();
310 m_length =
other.get_data_length();
311 m_response_status =
other.get_response_status();
312 m_byte_enable_length =
other.get_byte_enable_length();
313 m_streaming_width =
other.get_streaming_width();
314 m_gp_option =
other.get_gp_option();
315 m_dmi =
other.is_dmi_allowed();
318 m_data.resize(m_length);
326 m_byte_enable.resize(m_byte_enable_length);
329 m_byte_enable_length = 0;
330 m_byte_enable.clear();
333 void deep_copy_to_tlm(tlm::tlm_generic_payload&
other)
335 other.set_command((tlm::tlm_command)(m_command));
336 other.set_address(m_address);
337 other.set_data_length(m_length);
338 other.set_response_status((tlm::tlm_response_status)(m_response_status));
339 other.set_byte_enable_length(m_byte_enable_length);
340 other.set_streaming_width(m_streaming_width);
341 other.set_gp_option((tlm::tlm_gp_option)(m_gp_option));
342 other.set_dmi_allowed(m_dmi);
344 other.set_data_ptr(
nullptr);
346 other.set_data_ptr(
reinterpret_cast<unsigned char*
>(m_data.data()));
348 if (!m_byte_enable_length) {
349 other.set_byte_enable_ptr(
nullptr);
351 other.set_byte_enable_ptr(
reinterpret_cast<unsigned char*
>(m_byte_enable.data()));
355 void update_to_tlm(tlm::tlm_generic_payload&
other)
357 tlm::tlm_generic_payload
tmp;
359 tmp.set_data_ptr(
nullptr);
361 tmp.set_data_ptr(
reinterpret_cast<unsigned char*
>(m_data.data()));
364 if (!m_byte_enable_length) {
365 other.set_byte_enable_ptr(
nullptr);
367 tmp.set_byte_enable_ptr(
reinterpret_cast<unsigned char*
>(m_byte_enable.data()));
369 tmp.set_data_length(m_length);
370 tmp.set_byte_enable_length(m_byte_enable_length);
371 tmp.set_response_status((tlm::tlm_response_status)m_response_status);
372 tmp.set_dmi_allowed(m_dmi);
373 other.update_original_from(
tmp, m_byte_enable_length > 0);
377 cci::cci_broker_handle m_broker;
379 std::mutex m_cci_db_mut;
381 class initiator_socket_spying
382 :
public tlm_utils::simple_initiator_socket_b<MOD, BUSWIDTH, tlm::tlm_base_protocol_types,
383 sc_core::SC_ZERO_OR_MORE_BOUND>
385 using socket_type = tlm_utils::simple_initiator_socket_b<
MOD,
BUSWIDTH, tlm::tlm_base_protocol_types,
386 sc_core::SC_ZERO_OR_MORE_BOUND>;
387 using typename socket_type::base_target_socket_type;
390 const std::function<
void(std::string)> register_cb;
393 initiator_socket_spying(
const char* name,
const std::function<
void(std::string)>&
f)
394 : socket_type::simple_initiator_socket_b(name), register_cb(
f)
400 socket_type::bind(socket);
401 register_cb(socket.get_base_export().name());
405 void bind(tlm::tlm_initiator_socket<BUSWIDTH>& socket)
407 socket_type::bind(socket);
408 register_cb(socket.get_base_port().name());
413 std::string nameFromSocket(std::string s) {
return s; }
415 void remote_register_boundto(std::string s) {
SCP_DEBUG(()) <<
"Binding: " << s; }
423 using tlm_target_socket = tlm_utils::simple_target_socket_tagged_b<
MOD,
BUSWIDTH, tlm::tlm_base_protocol_types,
424 sc_core::SC_ZERO_OR_MORE_BOUND>;
426 sc_core::sc_vector<tlm_target_socket> target_sockets;
427 sc_core::sc_vector<initiator_socket_spying> initiator_sockets;
429 sc_core::sc_vector<InitiatorSignalSocket<bool>> initiator_signal_sockets;
430 sc_core::sc_vector<TargetSignalSocket<bool>> target_signal_sockets;
432 cci::cci_param<uint32_t> p_client_port;
433 cci::cci_param<uint32_t> p_server_port;
434 cci::cci_param<std::string> p_exec_path;
436 cci::cci_param<std::string> p_sync_policy;
437 cci::cci_param<uint32_t> p_tlm_initiator_ports_num;
438 cci::cci_param<uint32_t> p_tlm_target_ports_num;
439 cci::cci_param<uint32_t> p_initiator_signals_num;
440 cci::cci_param<uint32_t> p_target_signals_num;
443 rpc::client* client =
nullptr;
444 rpc::server* server =
nullptr;
446 std::condition_variable is_client_connected;
447 std::condition_variable is_sc_status_set;
448 std::mutex client_conncted_mut;
449 std::mutex sc_status_mut;
450 std::mutex stop_mutex;
451 std::atomic_bool cancel_waiting;
452 std::thread::id sc_tid;
453 std::queue<std::pair<int, bool>> sig_queue;
454 std::mutex sig_queue_mut;
455 sc_core::sc_status m_remote_status =
static_cast<sc_core::sc_status
>(0);
457 int targets_bound = 0;
472 std::queue<std::function<
void()>> notifiers;
473 std::thread notifier_thread;
474 std::atomic_bool is_stopped;
475 std::atomic_bool is_started;
478 std::vector<gs::async_event> data_ready_events;
479 std::vector<sc_core::sc_event> port_available_events;
480 std::vector<bool> is_port_busy;
481 std::condition_variable is_rpc_execed;
482 std::mutex start_stop_mutex;
483 std::mutex rpc_execed_mut;
493 while (!is_stopped) {
494 std::unique_lock<std::mutex>
ul(rpc_execed_mut);
495 is_rpc_execed.wait_for(
ul, std::chrono::milliseconds(RPC_TIMEOUT),
496 [
this]() {
return (!notifiers.empty() || is_stopped); });
497 while (!notifiers.empty()) {
508 , data_ready_events(
ev_num)
509 , port_available_events(
ev_num)
510 , is_port_busy(
ev_num,
false)
518 std::lock_guard<std::mutex>
start_lg(start_stop_mutex);
519 if (is_started)
return;
523 notifier_thread = std::thread(&trans_waiter::notifier_task,
this);
529 std::lock_guard<std::mutex>
stop_lg(start_stop_mutex);
530 if (is_stopped || !is_started)
return;
534 std::lock_guard<std::mutex>
lg(rpc_execed_mut);
535 is_rpc_execed.notify_one();
538 if (notifier_thread.joinable()) notifier_thread.join();
541 ~trans_waiter() { stop(); }
543 void enqueue_notifier(std::function<
void()> notifier) { notifiers.push(notifier); }
546 std::unique_ptr<trans_waiter> btspt_waiter;
548 template <
typename...
Args>
549 std::future<RPCLIB_MSGPACK::object_handle> do_rpc_async_call(std::string
const&
func_name,
Args... args)
554 std::future<RPCLIB_MSGPACK::object_handle>
ret;
556 ret = client->async_call(
func_name, std::forward<Args>(args)...);
557 }
catch (
const std::future_error&
e) {
558 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_call() Connection with remote is closed: " <<
e.what();
561 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_call() Unknown error!";
567 template <
typename T>
568 T do_rpc_async_get(std::future<RPCLIB_MSGPACK::object_handle>
fut)
573 }
catch (
const std::future_error&
e) {
574 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_get() RPC future is corrupted: " <<
e.what();
577 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_async_get() Unknown error!";
583 template <
typename T>
584 T do_rpc_as(RPCLIB_MSGPACK::object_handle
handle)
590 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_as() RPC remote value is corrupted!";
596 template <
typename...
Args>
597 RPCLIB_MSGPACK::object_handle do_rpc_call(std::string
const&
func_name,
Args... args)
602 RPCLIB_MSGPACK::object_handle
ret;
604 ret = client->call(
func_name, std::forward<Args>(args)...);
607 catch (
const std::future_error&
e) {
608 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_call() Connection with remote is closed: " <<
e.what();
611 SCP_DEBUG(()) << name() <<
" PassRPC::do_rpc_call() Unknown error!";
618 bool is_local_mode() {
return (m_container && m_is_local); }
620 void fw_b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
override
622 SCP_DEBUG(()) <<
"calling b_transport on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
623 initiator_sockets[id]->b_transport(
trans, delay);
624 SCP_DEBUG(()) <<
"return from b_transport on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
627 unsigned int fw_transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
override
629 SCP_DEBUG(()) <<
"calling transport_dbg on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
630 unsigned int ret = initiator_sockets[id]->transport_dbg(
trans);
631 SCP_DEBUG(()) <<
"return from transport_dbg on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
635 bool fw_get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
override
637 SCP_DEBUG(()) <<
"calling get_direct_mem_ptr on initiator_socket_" <<
id <<
" " << scp::scp_txn_tostring(
trans);
638 bool ret = initiator_sockets[id]->get_direct_mem_ptr(
trans, dmi_data);
639 SCP_DEBUG(()) <<
"return from get_direct_mem_ptr on initiator_socket_" <<
id <<
" "
640 <<
" RET: " << std::boolalpha <<
ret <<
" " << scp::scp_txn_tostring(
trans)
641 <<
" IS_READ_ALLOWED: " << std::boolalpha << dmi_data.is_read_allowed() <<
" "
642 <<
" IS_WRITE_ALLOWED: " << std::boolalpha << dmi_data.is_write_allowed();
646 void fw_invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
override
648 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
649 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
650 for (
int i = 0;
i < target_sockets.size();
i++) {
651 target_sockets[
i]->invalidate_direct_mem_ptr(start, end);
655 void fw_handle_signal(
int id,
bool value)
override
657 SCP_DEBUG(()) <<
"calling handle_signal on initiator_signal_socket_" <<
id <<
" value: " << std::boolalpha
659 initiator_signal_sockets[id]->write(value);
663 void b_transport(
int id, tlm::tlm_generic_payload&
trans, sc_core::sc_time& delay)
665 if (is_local_mode()) {
666 m_container->fw_b_transport(
id,
trans, delay);
670 while (btspt_waiter->is_port_busy[
id]) {
671 sc_core::wait(btspt_waiter->port_available_events[
id]);
673 btspt_waiter->is_port_busy[id] =
true;
675 tlm_generic_payload_rpc
t;
676 tlm_generic_payload_rpc r;
677 double time = sc_core::sc_time_stamp().to_seconds();
682 auto c = in_cache(addr);
686 switch (
trans.get_command()) {
687 case tlm::TLM_IGNORE_COMMAND:
689 case tlm::TLM_WRITE_COMMAND:
690 memcpy(
c->get_dmi_ptr() + (addr -
c->get_start_address()),
trans.get_data_ptr(),
len);
692 case tlm::TLM_READ_COMMAND:
693 memcpy(
trans.get_data_ptr(),
c->get_dmi_ptr() + (addr -
c->get_start_address()),
len);
696 trans.set_dmi_allowed(
true);
697 trans.set_response_status(tlm::TLM_OK_RESPONSE);
703 t.m_quantum_time = delay.to_seconds();
704 t.m_sc_time = sc_core::sc_time_stamp().to_seconds();
711 if (std::this_thread::get_id() == sc_tid && sc_core::sc_get_status() >= sc_core::sc_status::SC_RUNNING &&
712 sc_core::sc_get_curr_process_kind() != sc_core::sc_curr_proc_kind::SC_NO_PROC_) {
714 <<
" SC current process kind = " << sc_core::sc_get_curr_process_kind();
715 btspt_waiter->start();
717 std::unique_lock<std::mutex>
ul(btspt_waiter->rpc_execed_mut);
718 btspt_waiter->enqueue_notifier([&]() {
720 btspt_waiter->data_ready_events[id].async_notify();
722 btspt_waiter->is_rpc_execed.notify_one();
725 <<
" SC current process kind = " << sc_core::sc_get_curr_process_kind();
726 if (sc_core::sc_get_curr_process_kind() != sc_core::sc_curr_proc_kind::SC_METHOD_PROC_) {
727 sc_core::wait(btspt_waiter->data_ready_events[
id]);
729 SCP_FATAL(()) << name() <<
" b_transport was called from the context of SC_METHOD!";
735 r.update_to_tlm(
trans);
736 delay = sc_core::sc_time(r.m_quantum_time, sc_core::SC_SEC);
737 sc_core::sc_time
other_time = sc_core::sc_time(r.m_sc_time, sc_core::SC_SEC);
738 btspt_waiter->is_port_busy[id] =
false;
739 btspt_waiter->port_available_events[id].notify(sc_core::SC_ZERO_TIME);
741 tlm_generic_payload_rpc b_transport_rpc(
int id, tlm_generic_payload_rpc
t)
743 tlm::tlm_generic_payload
trans;
744 t.deep_copy_to_tlm(
trans);
745 sc_core::sc_time delay = sc_core::sc_time(
t.m_quantum_time, sc_core::SC_SEC);
746 sc_core::sc_time
other_time = sc_core::sc_time(
t.m_sc_time, sc_core::SC_SEC);
748 m_sc.
run_on_sysc([&] { initiator_sockets[id]->b_transport(
trans, delay); });
750 t.m_quantum_time = delay.to_seconds();
755 unsigned int transport_dbg(
int id, tlm::tlm_generic_payload&
trans)
757 if (is_local_mode()) {
758 return m_container->fw_transport_dbg(
id,
trans);
760 SCP_DEBUG(()) << name() <<
" ->remote debug tlm " << txn_str(
trans);
761 tlm_generic_payload_rpc
t;
762 tlm_generic_payload_rpc r;
766 r.update_to_tlm(
trans);
767 SCP_DEBUG(()) << name() <<
" <-remote debug tlm done " << txn_str(
trans);
769 return trans.get_response_status() == tlm::TLM_OK_RESPONSE ?
trans.get_data_length() : 0;
771 tlm_generic_payload_rpc transport_dbg_rpc(
int id, tlm_generic_payload_rpc
t)
773 tlm::tlm_generic_payload
trans;
774 t.deep_copy_to_tlm(
trans);
776 SCP_DEBUG(()) << name() <<
" remote-> debug tlm " << txn_str(
trans);
779 SCP_DEBUG(()) << name() <<
" remote<- debug tlm done " << txn_str(
trans);
781 if (!(
trans.get_data_length() ==
ret_len ||
trans.get_response_status() != tlm::TLM_OK_RESPONSE)) {
783 SCP_WARN(()) <<
"debug transaction not able to access required length of data.";
788 bool get_direct_mem_ptr(
int id, tlm::tlm_generic_payload&
trans, tlm::tlm_dmi& dmi_data)
790 if (is_local_mode()) {
791 return m_container->fw_get_direct_mem_ptr(
id,
trans, dmi_data);
794 SCP_DEBUG(()) <<
" " << name() <<
" get_direct_mem_ptr to address "
795 <<
"0x" << std::hex <<
trans.get_address();
798 c = in_cache(
trans.get_address());
801 return !(dmi_data.is_none_allowed());
804 tlm_generic_payload_rpc
t;
809 if (r.m_shmem_size == 0) {
810 SCP_DEBUG(()) << name() <<
"DMI OK, but no shared memory available?" <<
trans.get_address();
815 assert(m_dmi_cache.count(dmi_data.get_start_address()) == 0);
816 m_dmi_cache[dmi_data.get_start_address()] = dmi_data;
818 return !(dmi_data.is_none_allowed());
821 tlm_dmi_rpc get_direct_mem_ptr_rpc(
int id, tlm_generic_payload_rpc
t)
823 tlm::tlm_generic_payload
trans;
824 t.deep_copy_to_tlm(
trans);
826 SCP_DEBUG(()) <<
" " << name() <<
" get_direct_mem_ptr " << txn_str(
trans);
828 tlm::tlm_dmi dmi_data;
830 ret.m_shmem_size = 0;
831 if (initiator_sockets[
id]->get_direct_mem_ptr(
trans, dmi_data)) {
834 ret.from_tlm(dmi_data,
ext);
840 void invalidate_direct_mem_ptr(sc_dt::uint64 start, sc_dt::uint64 end)
842 if (is_local_mode()) {
843 m_container->fw_invalidate_direct_mem_ptr(start, end);
845 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
846 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
847 do_rpc_async_call(
"dmi_inv", start, end);
849 void invalidate_direct_mem_ptr_rpc(sc_dt::uint64 start, sc_dt::uint64 end)
851 SCP_DEBUG(()) <<
" " << name() <<
" invalidate_direct_mem_ptr "
852 <<
" start address 0x" << std::hex << start <<
" end address 0x" << std::hex << end;
854 cache_clean(start, end);
856 for (
int i = 0;
i < target_sockets.size();
i++) {
857 target_sockets[
i]->invalidate_direct_mem_ptr(start, end);
864 bool is_self_param(
const std::string& parent,
const std::string&
parname,
const std::string& value)
867 "args",
"moduletype",
"initiator_socket",
"target_socket",
"initiator_signal_socket",
"target_signal_socket"
870 std::string search_str = parent +
"." + entry;
871 if (entry ==
"moduletype" && value ==
"\"RemotePass\"") search_str = entry;
872 return parname.find(search_str) != std::string::npos;
876 str_pairs get_cci_db()
878 std::string parent = std::string(name());
880 for (
auto p : m_broker.get_unconsumed_preset_values()) {
881 std::string name =
p.first;
882 std::string
k =
p.first;
883 if (
k.find(parent) == 0) {
884 if (is_self_param(parent,
k,
p.second.to_json()))
continue;
885 k =
k.substr(parent.length() + 1);
886 ret.push_back(std::make_pair(
"$" +
k,
p.second.to_json()));
888 m_broker.ignore_unconsumed_preset_values(
889 [name](
const std::pair<std::string, cci::cci_value>&
iv) ->
bool {
return iv.first == name; });
890 }
else if (
k.find(
'.') == std::string::npos) {
891 ret.push_back(std::make_pair(
k,
p.second.to_json()));
897 void set_cci_db(str_pairs
db)
899 std::string
modname = std::string(name());
900 std::string parent = std::string(
modname).substr(0,
modname.find_last_of(
"."));
904 if (
p.first[0] ==
'$') {
905 parname = parent +
"." +
p.first.substr(1);
906 }
else if (
p.first[0] ==
'@') {
913 handle.set_cci_value(cci::cci_value::from_json(
p.second));
915 m_broker.set_preset_cci_value(
parname, cci::cci_value::from_json(
p.second));
923 : sc_core::sc_module(
nm)
924 , m_broker(cci::cci_get_broker())
925 , initiator_sockets(
"initiator_socket")
926 , target_sockets(
"target_socket")
927 , initiator_signal_sockets(
"initiator_signal_socket")
928 , target_signal_sockets(
"target_signal_socket")
929 , p_client_port(
"client_port", 0,
930 "The port that should be used to connect this client to the "
932 , p_server_port(
"server_port", 0,
"The port that should be used to server on")
933 , p_exec_path(
"exec_path",
"",
934 "The path to the executable that should be started by "
937 , p_sync_policy(
"sync_policy",
"multithread-unconstrained",
"Sync policy for the remote")
938 , p_tlm_initiator_ports_num(
"tlm_initiator_ports_num", 0,
"number of tlm initiator ports")
939 , p_tlm_target_ports_num(
"tlm_target_ports_num", 0,
"number of tlm target ports")
940 , p_initiator_signals_num(
"initiator_signals_num", 0,
"number of initiator signals")
941 , p_target_signals_num(
"target_signals_num", 0,
"number of target signals")
942 , cancel_waiting(
false)
944 SigHandler::get().add_sigint_handler(Handler_CB::PASS);
945 SigHandler::get().register_on_exit_cb(std::string(name()) +
".gs::PassRPC::stop", [
this]() { stop(); });
947 sc_tid = std::this_thread::get_id();
951 if (is_local_mode()) {
952 SCP_DEBUG(()) <<
"Working in LOCAL mode!";
954 SCP_DEBUG(()) << get_current_process_id() <<
" IS THE RPC PID, " << std::this_thread::get_id()
955 <<
" is the thread ID";
958 server =
new rpc::server(p_server_port);
959 server->suppress_exceptions(
true);
960 p_server_port = server->port();
961 assert(p_server_port > 0);
964 if (!in_server() && p_client_port.get_value() == 0) {
965 p_client_port = get_rpc_server_port();
970 server->bind(
"reg", [&](
int port) {
971 SCP_DEBUG(()) <<
"reg " << name() <<
", pid: " << get_current_process_id() <<
", port: " <<
port;
972 assert(p_client_port == 0 && client ==
nullptr);
973 p_client_port =
port;
974 if (!client) client =
new rpc::client(
"127.0.0.1", p_client_port);
975 std::unique_lock<std::mutex>
ul(client_conncted_mut);
976 is_client_connected.notify_one();
981 do_rpc_async_call(
"partner_handle",
984 do_rpc_async_call(
"sock_pair", pahandler.get_sockpair_fd0(), pahandler.get_sockpair_fd1());
990 server->bind(
"cci_db", [&](str_pairs
db) {
991 if (sc_core::sc_get_status() > sc_core::sc_status::SC_BEFORE_END_OF_ELABORATION) {
992 std::cerr <<
"Attempt to do cci_db() RPC after "
993 "sc_core::sc_status::SC_BEFORE_END_OF_ELABORATION"
997 std::lock_guard<std::mutex>
lg(m_cci_db_mut);
998 m_cci_db.insert(m_cci_db.end(),
db.begin(),
db.end());
1002 server->bind(
"status", [&](
int s) {
1003 SCP_DEBUG(()) <<
"SIMULATION STATE " << name() <<
" to status " << s;
1004 assert(s > m_remote_status);
1005 m_remote_status =
static_cast<sc_core::sc_status
>(s);
1006 std::lock_guard<std::mutex>
lg(sc_status_mut);
1007 is_sc_status_set.notify_one();
1011 server->bind(
"b_tspt", [&](
int id, tlm_generic_payload_rpc txn) {
1013 return PassRPC::b_transport_rpc(
id, txn);
1014 }
catch (std::runtime_error
const&
e) {
1015 std::cerr <<
"Main Error: '" <<
e.what() <<
"'\n";
1017 }
catch (
const std::exception&
exc) {
1018 std::cerr <<
"main Error: '" <<
exc.what() <<
"'\n";
1021 std::cerr <<
"Unknown error (main.cc)!\n";
1026 server->bind(
"dbg_tspt", [&](
int id, tlm_generic_payload_rpc txn) {
1028 return PassRPC::transport_dbg_rpc(
id, txn);
1032 return PassRPC::invalidate_direct_mem_ptr_rpc(start, end);
1035 server->bind(
"dmi_req",
1036 [&](
int id, tlm_generic_payload_rpc txn) {
return PassRPC::get_direct_mem_ptr_rpc(
id, txn); });
1038 server->bind(
"exit", [&](
int i) {
1041 rpc::this_session().post_exit();
1050 server->bind(
"signal", [&](
int i,
bool v) {
1051 if (sc_core::sc_get_status() < sc_core::sc_status::SC_START_OF_SIMULATION) {
1052 std::lock_guard<std::mutex>
lg(sig_queue_mut);
1053 sig_queue.push(std::make_pair(
i,
v));
1056 m_sc.
run_on_sysc([&] { initiator_signal_sockets[
i]->write(
v); },
1057 (sc_core::sc_get_status() < sc_core::sc_status::SC_RUNNING ?
false :
true));
1066 std::cerr <<
"remote process (" << get_current_process_id() <<
") detected parent ("
1075 std::cerr <<
"remote process (" <<
getpid() <<
") detected parent (" << pahandler.get_ppid()
1076 <<
") exit!" << std::endl;
1082 server->async_run(1);
1084 if (p_client_port) {
1085 SCP_INFO(()) <<
"Connecting client on port " << p_client_port;
1086 if (!client) client =
new rpc::client(
"127.0.0.1", p_client_port);
1091 btspt_waiter = std::make_unique<trans_waiter>(
"btspt_waiter", p_tlm_target_ports_num.get_value());
1093 initiator_sockets.init(p_tlm_initiator_ports_num.get_value(), [
this](
const char*
n,
int i) {
1094 return new initiator_socket_spying(n, [&](std::string s) -> void { remote_register_boundto(s); });
1096 target_sockets.init(p_tlm_target_ports_num.get_value(),
1097 [
this](
const char*
n,
int i) {
return new tlm_target_socket(
n); });
1098 initiator_signal_sockets.init(p_initiator_signals_num.get_value(),
1100 target_signal_sockets.init(p_target_signals_num.get_value(),
1103 for (
int i = 0;
i < p_tlm_target_ports_num.get_value();
i++) {
1104 target_sockets[
i].register_b_transport(
this, &PassRPC::b_transport,
i);
1105 target_sockets[
i].register_transport_dbg(
this, &PassRPC::transport_dbg,
i);
1106 target_sockets[
i].register_get_direct_mem_ptr(
this, &PassRPC::get_direct_mem_ptr,
i);
1109 for (
int i = 0;
i < p_tlm_initiator_ports_num.get_value();
i++) {
1110 initiator_sockets[
i].register_invalidate_direct_mem_ptr(
this, &PassRPC::invalidate_direct_mem_ptr);
1113 for (
int i = 0;
i < p_target_signals_num.get_value();
i++) {
1114 target_signal_sockets[
i].register_value_changed_cb([&,
i](
bool value) {
1115 if (is_local_mode()) {
1116 m_container->fw_handle_signal(
i, value);
1119 do_rpc_async_call(
"signal",
i, value);
1123 if (!is_local_mode()) {
1132 std::unique_lock<std::mutex>
ul(client_conncted_mut);
1133 is_client_connected.wait(
ul, [&]() {
return (p_client_port > 0 || cancel_waiting); });
1161 m_child_pid =
fork();
1163 if (m_child_pid > 0) {
1164 pahandler.setup_parent_conn_checker();
1165 SigHandler::get().set_nosig_chld_stop();
1166 SigHandler::get().add_sigchld_handler(Handler_CB::EXIT);
1167 }
else if (m_child_pid == 0) {
1170 SCP_FATAL(()) <<
"Unable to exec the remote child process, '" << p_exec_path.get_value()
1171 <<
"', error: " << std::strerror(
errno);
1173 SCP_FATAL(()) <<
"failed to fork remote process, error: " << std::strerror(
errno);
1177 int get_current_process_id() {
return getpid(); }
1180 bool in_server() {
return !p_exec_path.get_value().empty(); }
1182 void build_remote_cmdline(std::list<std::string>&
remote_cmdline)
1189 remote_cmdline.push_back(
"rpc_server_port=" + std::to_string(p_server_port.get_value()));
1200 SCP_DEBUG(()) <<
"SIMULATION STATE send " << name() <<
" to status " << sc_core::sc_get_status();
1201 do_rpc_call(
"status",
static_cast<int>(sc_core::sc_get_status()));
1202 std::unique_lock<std::mutex>
ul(sc_status_mut);
1203 is_sc_status_set.wait(
ul, [&]() {
return (m_remote_status >= sc_core::sc_get_status() || cancel_waiting); });
1205 SCP_DEBUG(()) <<
"SIMULATION STATE synced " << name() <<
" to status " << sc_core::sc_get_status();
1208 void handle_before_sim_start_signals()
1210 std::lock_guard<std::mutex>
lg(sig_queue_mut);
1211 while (!sig_queue.empty()) {
1212 std::pair<int, bool>
sig = sig_queue.front();
1214 m_sc.run_on_sysc([&] { initiator_signal_sockets[
sig.first]->write(
sig.second); },
false);
1220 auto handle = m_broker.get_param_handle(
"rpc_server_port");
1225 }
catch (
const std::exception&
e) {
1226 std::cerr <<
e.what() <<
'\n';
1239 std::lock_guard<std::mutex>
lg(stop_mutex);
1240 if (cancel_waiting || is_local_mode())
return;
1241 cancel_waiting =
true;
1244 std::lock_guard<std::mutex>
cc_lg(client_conncted_mut);
1245 is_client_connected.notify_one();
1248 std::lock_guard<std::mutex>
scs_lg(sc_status_mut);
1249 is_sc_status_set.notify_one();
1251 btspt_waiter->stop();
1253 server->close_sessions();
1259 do_rpc_async_call(
"exit", 0);
1265 void stop_and_exit()
1271 void before_end_of_elaboration()
override
1273 if (is_local_mode())
return;
1275 std::lock_guard<std::mutex>
lg(m_cci_db_mut);
1276 set_cci_db(m_cci_db);
1279 void end_of_elaboration()
override
1281 if (is_local_mode())
return;
1285 void start_of_simulation()
override
1287 if (is_local_mode())
return;
1289 handle_before_sim_start_signals();
1293 PassRPC(
const PassRPC&) =
delete;
1296 SigHandler::get().deregister_on_exit_cb(std::string(name()) +
".gs::PassRPC::stop");
1297 if (is_local_mode())
return;
1301 m_dmi_cache.clear();
1305 void end_of_simulation()
override
1307 if (is_local_mode())
return;