Jump to content
shanh

async_request_update() multiple events

Recommended Posts

A small example of async_request_event. It only triggers the first event and not the second one? Can anyone please explain why?

 

#include <systemc>
#include <unistd.h>
#include <thread>

using namespace sc_core;

class ThreadSafeEventIf : public sc_interface {
    virtual void notify(sc_time delay = SC_ZERO_TIME) = 0;
    virtual const sc_event &default_event(void) const = 0;
protected:
    virtual void update(void) = 0;
};

class ThreadSafeEvent : public sc_prim_channel, public ThreadSafeEventIf {
public:
    ThreadSafeEvent(const char *name = ""): event(name) {}

    void notify(sc_time delay = SC_ZERO_TIME) {
        this->delay = delay;
        async_request_update();
    }

    const sc_event &default_event(void) const {
        return event;
    }
protected:
    virtual void update(void) {
        event.notify(delay);
    }
    sc_event event;
    sc_time delay;
};

SC_MODULE(Foo)
{
public:
    SC_CTOR(Foo)
    {
        SC_THREAD(main);

        SC_METHOD(eventTriggered);
        sensitive << event;
        dont_initialize();
    }
private:
    void main() {
        usleep(5 * 1000 * 1000); // Just for the example, event is added to pending events during this sleep
        wait(SC_ZERO_TIME); // Schedule (event is evaluated here)
        usleep(1 * 1000 * 1000); // Just for the example
        std::cout << "Done" << std::endl;
    }

    void eventTriggered() {
        std::cout << "Got event" << std::endl;
        std::cout << "sc_time " << sc_time_stamp() << std::endl;
    }

public:
    ThreadSafeEvent event;
};

void externalHostThread(void *arg, int d) {
    usleep(1 * 1000 * 1000); // Just for the example
    Foo* foo = (Foo*)(arg);
    foo->event.notify(sc_time(d,SC_NS));
    std::cout << "Event notified from an external host thread" << std::endl;
      
}

int sc_main(int argc, char *argv[])
{
    Foo foo("foo");
    int delay1 = 10;
    int delay2 = 15;
    std::thread t1(externalHostThread, &foo, delay1);
    std::thread t2(externalHostThread, &foo, delay2);
    sc_start();
   

    t1.join();
    t2.join();

    return 0;
}

Share this post


Link to post
Share on other sites

Remember that the SystemC OS thread is completely asynchronous to external threads and processes. Async_request_update() simply says to call update() once at the end of the delta cycle for a single object. So you can get multiple notifications within the same delta and only get one call-back. To keep from losing these you should setup a threadsafe mailbox/queue. Rather than just notify the event, you should also put an entry into the mailbox on each activation. Then your threadsafe update() method can see the multiple requests accurately.

Share this post


Link to post
Share on other sites

Hi shanh,

looking at the SystemC LRM:

 

Quote

 

5.9.6 Multiple event notifications
A given event shall have no more than one pending notification.

If function notify is called for an event that already has a notification pending, then only the notification scheduled to occur at the earliest time shall survive. The notification scheduled to occur at the later time shall be cancelled (or never be scheduled in the first place).


 

this is what happens in your example. The event is notified while another event is pending since your 2 threads sleep for the same amount of time. You would need to guard the event notification, use 2 separate events or an event queue similar to tlm_utils::peq_with_cb_and_phase.

Best regards

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

×