Jump to content

where are the delta cycles coming from


Recommended Posts

#include <systemc>
using namespace sc_core;

    sc_signal<int> s1 {nullptr}, s2 {nullptr};
        sensitive << s1 << s2;
    void producer1() {
        int v = 1;
        while (true) {
            wait(1, SC_SEC);
    void producer2() {
        int v = 100;
        while (true) {
            s2 = v++;
            wait(2, SC_SEC);
    void consumer() {
        while (true) {
            std::cout << sc_time_stamp() << ":" << sc_delta_count() << ":"
                      << (s1.event() ? s1.read() : 999) << ":" << (s2.event() ? s2.read() : 999)
                      << '\n';

int sc_main(int, char*[]) {
    SIGNAL_EVENT signal_event("signal_event");
    sc_start(4, SC_SEC);
    std::cout << sc_time_stamp() << "- delta - " << sc_delta_count() << '\n';
    return 0;
0 s:1:1:100
1 s:3:2:999
2 s:5:3:101
3 s:7:4:999
4 s- delta - 8

In the above code, at timestamp 0("0 s"), why s1 and s2 become 1 and 100 and delta account increase by 1? I see no delta notification or wait(SC_ZERO_TIME) or  notify() to make the 'update' to happen, the process consumer itself is in a waiting-list due to dont_initialize but somehow it becomes runnable.  Who triggered an update-cycle in the current simulation time 0 that leads process consumer to get new values from s1 and s2?

then after the first "0 s" timestamp, each additional second the delta_count increase 2, again I don't know where they're from.  Now s1 and s2 updates do make sense, they're updated after wait() which is normal.

Link to comment
Share on other sites

Thanks! I checked the code and read more. Now I understand elaboration phase sc_prim_channel assignments(write(v++) above) will lead to update-requests that will be processed at initialization phase, so at sc_time_stamp 0, s1.read() and s1.read() will have their newest (initial) value from elaboration phase.

The LRM also states elaboration phase can produce delta-notification, I could not find any example of that, how are they produced, by what?

I understand at initialization phase the simulator will do below things: 

1. run update-requests

2. put processes to runnable list and waiting list(i.e. dont_initialization)

3. run delta notifications(from elaboration phase, but how and why?)

4. enter evaluation phase and run the runnable processes

5. run update phase

6. run delta notification phase(again)

7. advance the simulation time and back to evaluation phase of some process


Link to comment
Share on other sites

An additional question about https://github.com/dcblack/SystemC-Engine , the scheduler looks very complex in a not-too-long example. That implies in a real design it could be very bug-prone when just a few e.notify() and time() are used. I'm new to SystemC, what's the "right way to do SystemC" here as far as scheduler is concerned?

In the software world as long as my shared data is mutex/semaphore/atomic protected we let the OS scheduler to do the rest, in SystemC it seems we not only need to do the shared-data part, we also need know the scheduler to its full detail? and worse, our code has to be scheduler-aware(all the intertwined wait/notify/delay/immediate-notify calls will be very messy fast), how to stay sane to avoid bugs related the you-have-to-know-scheduler-very-well-among-intertwined-notification-wait-calls?

Link to comment
Share on other sites

Quite the opposite. Because SystemC uses cooperative multi-tasking (which also implies single threaded in the OS world), then coding is much simpler. That is precisely why they chose to use cooperative multitasking. This is identical to the model used by Verilog, SystemVerilog and VHDL. Hardware engineers do not want to be concerned with mutexes and data sharing. Furthermore, most of the time (99.9%) we simply don't worry about delta cycles. The time when you might worry about them is when you have to write your own primitive channels.

From reading your questions, it seems clear that you are not following the simulation model very well. You need to keep in mind that SystemC processes are not pre-emptive. There is no way for a process to interrupt another process.

One other area, which gets some programmers into trouble is when they try to introduce OS parallelism into the picture without a clear understanding that the SystemC scheduler is NOT OS thread-safe. That requires special handling and is an advanced topic. SC_THREADs and SC_METHODs are not real OS processes. SystemC processes cooperate with one another by yielding at points when they are ready to give up control. The yielding statement is `sc_core::wait` with all its overloads

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.

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...