Jump to content

async_request_update() multiple events


shanh

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

Link to comment
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.

Link to comment
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

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...