Jump to content
pgarg

async_request_update example

Recommended Posts

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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);

}

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×