pgarg 0 Report post Posted November 2, 2012 I have a process that is asynchronous/external to SystemC Kernel. I want this process to generate an event to a systemC thread. I read on forums that there is mechanism - "async_request_update" - in system 2.3.0 to do so without corrupting systemC kernel data structures. Is there an example showing how to use this mechanism with OSCI simulator? Thanks Piyush Quote Share this post Link to post Share on other sites
Philipp A Hartmann 238 Report post Posted November 2, 2012 There is no real tutorial example available, yet. But you can look at the SystemC regression tests [1], which have a small test included at tests/systemc/1666-2011-compliance/async_request_update/ Greetings from Oldenburg, Philipp [1] http://www.accellera..._2-3_2012-07-02 1 maehne reacted to this Quote Share this post Link to post Share on other sites
David Black 154 Report post Posted November 2, 2012 struct thread_safe_event_if : sc_core::sc_interface { virtual void notify(sc_core::sc_time delay = SC_ZERO_TIME) = 0; virtual const sc_core::sc_event& default_event(void) const = 0; protected: virtual void update(void) = 0; }; struct thread_safe_event_channel : sc_core::sc_prim_channel, thread_safe_event_if { thread_safe_channel(const char* name); void notify(sc_core::sc_time delay = SC_ZERO_TIME); const sc_core::sc_event& default_event(void) const; protected: virtual void update(void); private: sc_core::sc_event m_event; sc_core::sc_time m_delay; }; // The following may be safely called from outside the SystemC OS thread void thread_safe_event_channel::notify(sc_core::sc_time delay) { m_delay = delay; async_request_update(); } const sc_core::sc_event& thread_safe_event_channel::default_event(void) { return m_event; } virtual void update(void) { m_event.notify(m_delay); } 2 maehne and Philipp A Hartmann reacted to this Quote Share this post Link to post Share on other sites
pgarg 0 Report post Posted November 2, 2012 There is no real tutorial example available, yet. But you can look at the SystemC regression tests [1], which have a small test included at tests/systemc/1666-2011-compliance/async_request_update/ Greetings from Oldenburg, Philipp [1] http://www.accellera..._2-3_2012-07-02 Hi Philipp There is no test directory at the path specified by you in systemc_regressions-2.3.0. There is async_reset and async_reset_port but no async_request_update? Regards Piyush Quote Share this post Link to post Share on other sites
Philipp A Hartmann 238 Report post Posted November 2, 2012 Oh, sorry. My mistake. The mentioned test has not been part of the 2.3.0 release. There may be some similar test included in the next version of SystemC… For now, you should use David's example as a reference. As in any (host) parallel programming, make sure to properly protect any shared data used in both parts (SystemC and other OS threads). This is not automatically addressed by the async_request_update mechanism. Sorry for the noise, Philipp Quote Share this post Link to post Share on other sites
David Black 154 Report post Posted November 2, 2012 I should probably note that using a non-default delay in my example probably does not make sense. Also this example could lose notifications in the sense that if SystemC has not yet serviced a notification, a subsequent notification will simply overwrite the previous one. I generally setup a handshake to ensure the external notifier knows it was received. You could also make a more elaborate notify method that sets/clears a "busy" flag. Be careful to properly protect shared data as Philipp points out. 1 maehne reacted to this Quote Share this post Link to post Share on other sites
pgarg 0 Report post Posted November 3, 2012 Hi David and Philipp, Thanks for the example. This example works for me. As David mention that newer notification will simply overwrite previous notification even though time delta for newer is larger than previous notification. This is fine in my case as in my case the time delta is always zero. As long as event can be delivered i am fine. To understand what is meant by shared data, let me elaborate my scenario. The shared data structure in my case is a queue<int>. My external thread looks as following grab pthread_mutex push a value in queue. thread_safe_event.notify(); // from David's example release pthread_mutex SystemC thread while(1) { wait( thread_safe_event.default_event() ); grab pthread_mutex pop all values from queue. release phtread_mutex; process values poped from queue. } Does this cover shared data structure protection for my case or do i need add mutexing within thread_safe_event as well? I am asking the question because in David's example m_delay variable essentially a shared variable between external thread and systemC kernel. external thread writes to variable and systemC kernel reads the variable? Thanks Piyush Quote Share this post Link to post Share on other sites
Philipp A Hartmann 238 Report post Posted November 5, 2012 Your solution looks correct. You may want to consider wrapping all of this together in a single "thread-safe input queue" for better encapsulation (and to remove the pthread stuff from your SystemC model). In this case, you can duplicate the queues internally: At protected one for pushing from the outside and a SystemC-local one, where to store the tokens that you need to process within the SystemC part of the model. With a swap of these queues in the update step, you can keep the locking times minimal. Secondly, if you accept a slight extension beyond the plain 1666-2011 standard, you can use sc_scoped_lock and sc_host_mutex instead of the plain pthread_mutex_* API (untested): template< typename T> class async_fifo : public tlm::tlm_blocking_get_if<T> // whatever fits your needs best , public sc_core::sc_prim_channel { sc_core::sc_host_mutex mtx_; // host-locking (e.g. pthread_mutex) sc_core::sc_event written_; std::deque<T> pushq_, popq_; public: async_fifo( const char* nm ) : sc_core::sc_prim_channel(nm) {} /* implement SystemC side interface (e.g. tlm_blocking_get_if) based on pop-queue */ void write_async( T const & v ) { { sc_core::sc_scoped_lock lock( mtx_ ); // critical section pusq_.push_back( v ); // append new value to queue } async_request_update(); } private: void update() { sc_assert( ! popq_.size() ); // make sure, everything is consumed by now { sc_core::sc_scoped_lock lock( mtx_ ); // critical section popq_.swap( pushq_ ); // move all pending tokens to pop-queue } written_.notify( sc_core::SC_ZERO_TIME ); } }; // async_fifo In David's original example, m_delay is indeed not fully protected. But as he already pointed out, you may miss updates (and notifications) anyhow. On the lower level, the compiler should be able to update m_delay in a single instruction, which at least prevents broken values. (You may want to check the assembly for this.) Greetings from Oldenburg, Philipp 1 maehne reacted to this Quote Share this post Link to post Share on other sites