An Introduction to SystemC Events

By John
September 19, 2022

In this post we take a closer look at events in SystemC. This includes a discussion of the sc_event class, the notify method and event queues.

SystemC is actually a set of classes and libraries which are built on top of the C++ programming language. We can download and install these libraries for free from the Accellera website.

As a result of this, the basic syntax of SystemC is taken directly from the C++ language.

However, in these tutorials we will only look at the SystemC extensions which we can use in FPGA design and verification.

Therefore, if you are not already familiar with the C++ language then it is a good idea to take a beginners C++ course before reading through these tutorials.

The sc_event Class

In SystemC, we use events in order to synchronize the running of the different processes in our design.

In simple terms, we use events to determine when our processes are executed, suspended and resumed.

We have actually already seen this in action in the posts on the SystemC scheduler and SystemC processes.

Whenever we call the wait method inside of a process, we are actually waiting for an event to occur.

In SystemC, we derive all events from the sc_event class. This class implements the notify method which we use to trigger our event.

The code snippet below shows the general syntax we use to declare an event in SystemC.

sc_event <event_name>;

We use the <event_name> field to give a unique name of our event.

Let's have a closer look at how we use events in SystemC.

Triggering SystemC Events with the Notify Method

In the post on the SystemC scheduler, we saw how we use the notify method to create time and delta notifications.

We actually call the notify method on SystemC events. This method is included as part of the sc_event class.

Whenever we call the notify method, we are signalling to our simulator that we need to run any processes which are waiting for this event.

However, we can only have 1 active notification for any event in our design.

Therefore, if we call the notify method on an event which already has a pending notification, the scheduler will ignore all but one of our notifications.

Normally, only the notification that is scheduled to occur earliest is recognized by the scheduler.

The code snippet below shows the general syntax we use to call the notify method in SystemC.

// Create an immediate notification
<event_name>.notify();

// Create a delta notification
<event_name>.notify(SC_ZERO_TIME);

// Create a time notification
<event_name>.notify(<n>, SC_NS);

In this code snippet, we use the <event_name> field to show which event we are calling the notify method on.

As we can see from this, we can create three different types of notification using the notify method.

The type of notification that we create depends on the arguments that we pass to the notify method.

When we call the notify method without any arguments, we create an immediate notification.

When we want to create a delta notification, we pass the SC_ZERO_TIME constant as an argument.

Finally, when we call with a time argument then we create a time notification.

Let's take a look at the different types of notification in a bit more detail.

Immediate Notifications

Immediate notifications are the simplest type of notification that we can create in SystemC.

When we create an immediate notification, the SystemC scheduler will process the notification as soon as it is called.

As a result of this, our notification is active in the same delta cycle that it is called in.

Any processes that are sensitive to the event will be run again as soon as we create an immediate notification.

Immediate Notification Example

To better demonstrate how immediate notifications work, let's have a look at a basic example.

For this example, we will create 2 immediate notifications with a 1 ns delay between them.

The code snippet below shows the code we will use to do this.

// Create 2 immediate notifications on e1
for (int i = 0; i < 2; i++) {  
  e1.notify();
  wait(1, SC_NS);
}

We will then create a process which simply waits for this event to occur. Whenever this process detects that an event has occurred, it will print the time and the current delta cycle count to the console.

The code snippet below shows the SystemC code we use to do this.

  void wait_on_notify() {
    while (true) {
      wait(e1);
      print_event_info();
    }
  }

Finally, we can simulate this example on EDA playground to see how immediate events work in SystemC. The console output below shows the result of running this simulation.

0 s : Immediate notification e1 created in delta cycle 0
0 s : Event detected in delta cycle 0
1 ns : Immediate notification e1 created in delta cycle 1
1 ns : Event detected in delta cycle 1

As we can see from this, whenever we create an immediate notification, it is implemented in the same delta cycle that it was created in.

This separates it from the other types of notification which are acted upon at a later time, as we will come to see.

Delta Notifications

When we create delta notifications, we are telling the SystemC scheduler that our event should be active in the next delta cycle.

This means that the scheduler will not start processing our notification until it reaches the delta notification state.

As a result of this, when we create a delta notification it is not acted upon until the next delta cycle.

This means that any of our processes which are sensitive to the event will be run again in the next delta cycle.

Delta Notification Example

In order to better understand how delta notifications work, let's consider a very basic example.

For this example, we will write some code which creates 2 delta notification with a 1ns delay between them.

The code snippet below shows how we would implement this in SystemC.

   	// Create 2 delta notifications on e1
    for (int i = 0; i < 2; i++) { 
      e1.notify(SC_ZERO_TIME);
      wait(1, SC_NS);
    }

We will then write a process which simply waits for this event to occur. Whenever this process detects that an event has occurred, it will print the time and the current delta cycle count to the console.

The code snippet below shows the SystemC code we use to do this.

  void wait_on_notify() {
    while (true) {
      wait(e1);
      print_event_info();
    }
  }

Finally, we can simulate this example on EDA playground to see how delta notifications work in practise. The console output below shows the result of running this simulation.

2 ns : Delta notification e1 created in delta cycle 2
2 ns : Event detected in delta cycle 3
3 ns : Delta notification e1 created in delta cycle 4
3 ns : Event detected in delta cycle 5

As we can see from this example, after we create a delta notification there is a delay of 1 delta cycle before it is active.

For example, we can see that the first delta notification we create occurs in delta cycle 2.

However, we can also then see that our wait_on_notify method isn't triggered by this event until delta cycle 3.

This clearly shows that the process is not triggered until the next delta cycle.

Time Notifications

The final type of notification that we can create are known as time notifications.

When we create time notifications, we are telling our scheduler that we want our event to be active at some point in the future.

This means that any of our processes which are sensitive to the event will be run again in the appropriate time step.

For example, if we create a 50ns time notification then we are telling our scheduler than we want our event to be active in 50ns.

As a result of this, any processes which wait on this event will be triggered again after a further 50ns of simulation time has elapsed.

Time Notification Example

To better understand how time notifications work, let's look at a basic example.

For this simple example we will create a 10ns time notification. The code snippet below shows how we do this in SystemC.

e1.notify(10, SC_NS);

We will then write a process which simply waits for this event to occur. Whenever this process detects that an event has occurred, it will print the simulation time and the current delta cycle count to the console.

The code snippet below shows the SystemC code we use to do this.

  void wait_on_notify() {
    while (true) {
      wait(e1);
      print_event_info();
    }
  }

Finally, we can simulate this example on EDA playground to see how time notifications work in practise. The console output below shows the result of running this simulation.

4 ns : Time notification (10ns) e1 created in delta cycle 6
14 ns : Event detected in delta cycle 9

As we can see from this example, we create our 10ns time notification after 4ns of our simulation time has elapsed.

We also then see that our wait_on_notify method isn't triggered by this event until 14ns of our time simulation has elapsed.

As we expect, this means that 10ns of simulation time has passed between creating and receiving the time notification.

SystemC Event Queues

When we use the sc_event class to create events in SystemC, we can only ever have one pending notification.

As result of this, the scheduler will ignore all but one of the pending notifications.

Normally, the scheduler only recognizes the notification that is scheduled to occur earliest.

However, we may also have instances where we need to create multiple pending notifications.

When we need to do this, we use the sc_event_queue class.

The code snippet below shows the general syntax we use to declare sc_event_queue objects in SystemC.

sc_event_queue <event_name>;

In this construct, we use the <event_name> field to give a unique to our sc_event_queue object.

Like the sc_event class, the sc_event_queue implements the notify method. We use this method when we want to trigger an event, as we discussed previously.

As a result of this, the method we use to trigger events is virtually the same for both sc_event objects and sc_event_queue objects.

However, we can only create time or delta notifications when we use the sc_event_queue class.

As a result of this, we must always pass a time argument to the notify method when we call it on an sc_event_queue object.

We can also pass the SC_ZERO_TIME constant as this is implemented as a time type in the SystemC libraries.

In addition to this, we can only use sc_event_queue objects in static sensitivity lists.

Apart from these limitations, we use the notify method in the same way on both sc_event objects and sc_event_queue objects.

The code snippet below shows how we create time and delta notifications in practise.

sc_event_queue example_q;

// Create a delta notification
example_q.notify(SC_ZERO_TIME);

// Create a 10 ns time notification 
example_q.notify(10, SC_NS);

In addition to the sc_event_queue class, we can also use the sc_event_queue_if class if we want to include an event queue in a module port.

Event Queue Example

In order to better understand how we use event queues in SystemC, let's look at a simple example.

For this example, we will firstly declare an sc_event_queue object and then call the notify method a total of 5 times in the same delta cycle.

We will do this inside of a for loop and use the loop variable as an argument to the notify method. This will allow us to create 5 notifications which are separated by 1 ns.

The code snippet below shows how we do this.

void create_events() {
  for (int i=0; i<5; i++) {
    e1.notify(i, SC_NS);
  }
}

In order to show how these events are created, we then write a simple process which just waits for this event to occur.

Whenever this process detects that an event has occurred, it will print the simulation time and delta cycle count to the console.

The code snippet below shows the SystemC code we use to do this.

void wait_for_event() {
  while (true) {
    wait();
    print_event_info();
  }
}

Finally, we can simulate this example on EDA playground to see how event queues work in practise. The console output below shows the result of running this simulation.

0 s :  called notify on e1 in delta cycle 0
0 s :  called notify on e1 in delta cycle 0
0 s :  called notify on e1 in delta cycle 0
0 s :  called notify on e1 in delta cycle 0
0 s :  called notify on e1 in delta cycle 0
0 s : Event detected in delta cycle 1
1 ns : Event detected in delta cycle 2
2 ns : Event detected in delta cycle 3
3 ns : Event detected in delta cycle 4
4 ns : Event detected in delta cycle 5

In this example we can see that we are creating 5 notifications on our event queue in the first delta cycle.

If we were to do this using normal event queue, only 1 of our notifications would be executed. As the first notifications is 0ns (i.e. a delta notification) only this notification would be active.

However, with the event queue, we can see that all 5 of our events are created and executed as expected.

Exercises

Which method is implemented in the sc_event class?

The notify method is implemented inside of the sc_event class.

What happens if we have attempt to create more than one notification at a time on an sc_event object.

When we have more than one pending notification for a sc_event object, only the earliest notification will be valid. Any other notifications that we have attempted to create will be ignored.

Name the three different types of notification that we can create in SystemC.

We can create immediate notifications, delta notifications and time notifications in SystemC.

What is the main difference between the sc_event and sc_event_queue classes?

We can only have one activate notification pending when we use the sc_event class. In contrast, we can have multiple notifications pending when we use the sc_event_queue class.

Which types of notification can we use for sc_event_class objects?

We can only create time and delta notifications on sc_event_class objects.

Enjoyed this post? Why not share it with others.

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe

Join our mailing list and be the first to hear about our latest FPGA tutorials
Sign Up to our Mailing List
© 2024 FPGA Tutorial

Sign up free for exclusive content.

Don't Miss Out

We are about to launch exclusive video content. Sign up to hear about it first.

Close
The fpgatutorial.com site logo

Don't Miss Out

We are about to launch exclusive video content. Sign up to hear about it first.

Close