SystemVerilog: Fine grain process control

Continuing from my previous post about Process vs Threads, now let’s discuss about SystemVerilog processes. Systemverilog has a built in class named Process that allows one process to access and control other processes/threads.

When we fork off any thread, a new object of process class is created at that time. This object contains status information about that thread. An attempt to create a user defined object of process class will result in error.

Reading from IEEE 1800-2012, the process class includes following:

class process;
typedef enum { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED } state;
static function process self();
function state status();
function void kill();
task await();
function void suspend();
function void resume();
function void srandom( int seed );
function string get_randstate();
function void set_randstate( string state );
endclass

Intuitively, following is short description about the tasks:

self()  will return the handle of the process.

status() will return information about which mode the current thread is.

kill() will kill the thread.

await() waits for some other thread to complete.

suspend() suspends the thread for some indefinite time.

resume() resumes the thread from suspended state.

This was all theoretical part about processes. Let’s look at an example:

Let’s say I have a protocol that sends five packets concurrently to the RTL on five similar but distinct interfaces. RTL triggers an event/signal when it has accepted a packet. But, when the RTL accepts fourth numbered packet (this can be any random numbered packet also), the second numbered packet (this can also be some random numbered packet) must be dropped off and not be sent to RTL. But the rest of packets (1st, 3rd and 5th packet) must be sent.

So, I will fork off five processes (named fork_all_processes in code below) in my testbench which invokes same task (named run_task in the code below). Take a handle of each process that gets forked off.

Now, in the thread for the process that is to be killed (2nd process over here),wait for the other process completion (4th process here). In the process 4, I will look for whether process 2 thread is running or not. If it is still running, when the trigger event for process 4 is triggered, then kill the process 2. If process 2 is already completed before process 4, then we have to kill nothing.

In this way, we can have a fine grain control over different threads executing concurrently. I know it seems bit confusing at first look, but the code might make it simple:


module top();
class process_ex; // class that forks all processes
process p[]; // number of processes
event ev[]; // events triggered by RTL for each process
int wait_process,kill_process; // process number which is to be awaited and killed

function new(int num_process); // constructor
p = new[num_process]; // handle of processes
ev = new[num_process];
endfunction

function void fork_all_processes(int num_process); // fork all the processes
for(int i=0; i<num_process;i++)
fork
automatic int j=i;
begin
p[j] = process::self(); // get object of current processs
run_task(j); // send some stimulus to RTL
end
join_none
endfunction

function void assign_wait_kill_process(int wait_process,int kill_process);
this.wait_process = wait_process; // number of process that is to be awaited
this.kill_process = kill_process; // number of process that is to be killed
endfunction

task automatic run_task(int i);
process::state pstat;
wait(p[kill_process] != null); // wait till the killing process starts (Process-2)
pstat = p[kill_process].status(); // get status for killing process (Process-2)
$display($time,"\tWaiting for trigger of %0d event",i);
wait(ev[i].triggered); // wait for current process event tirgger
if(i==wait_process) begin // if the current process is the process which was to be awaited (Process-4)
$display($time,"\tProcess %0d found that p[%0d] is %0s",wait_process,kill_process,pstat.name);
if(pstat == process::RUNNING || pstat == process::WAITING) begin // check the status of killing process (Process-2)
$display($time,"\tProcess %0d found running/waiting",kill_process);
p[kill_process].kill(); // kill the process (Process-2)
$display($time,"\tProcess %0d killed",kill_process);
end

end
$display($time,"\tWait completed for trigger of %0d event",i); // current process completed successfully
endtask

endclass

process_ex proc = new(5);
initial begin
proc.assign_wait_kill_process(4,2); // Some random number. When process 4 completes, kill process 2 also
proc.fork_all_processes(5);
for(int i=0;i proc.ev[j]; // assume this is triggered by RTL
$display($time,"\tTriggered %0d event",j);
end
join_none
end
end

initial begin
#1000 $finish;
end
endmodule

OUTPUT:

0 Waiting for trigger of 2 event
0 Waiting for trigger of 3 event
0 Waiting for trigger of 4 event
0 Waiting for trigger of 0 event
0 Waiting for trigger of 1 event
5 Triggered 4 event
5 Process 4 found that p[2] is WAITING
5 Process 2 found running/waiting
5 Process 2 killed
5 Wait completed for trigger of 4 event
8 Triggered 1 event
8 Triggered 2 event
8 Wait completed for trigger of 1 event
9 Triggered 0 event
9 Triggered 3 event
9 Wait completed for trigger of 0 event
9 Wait completed for trigger of 3 event

We can see that when the trigger event for process 4 was triggered, it killed process 2 and the “Wait completed for process 2” statement never arrived.

Section 9.7 of IEEE 1800-2012 gives some information about fine grain process control. Hope you found this post useful. Pardon me for the indentation over here. Feel free to raise queries and experiment the above code.

10 responses

  1. […] Upcoming: SystemVerilog: Fine grain process control. […]

    Like

  2. SV Process is not like a process in windows or in Linux.

    SV Processes can share memory like threads do. SV processes are actually what coroutines are in programming world. SV Processes are user level threads. Processes get run on the same OS thread in a sequential manner.

    Liked by 1 person

    1. Totally agree. SV processes are actually the threads running under a single process (single executable file). The class is named as process, the object of which is actually a handle of thread. 😉

      Like

  3. for(int i=0;i proc.ev[j]; // assume this is triggered by RTL
    $display($time,”\tTriggered %0d event”,j);
    end

    I think some lines of code are skipped, i tried but i am getting errors, can you please compeleted those missing lines.

    thanks and regards,
    tarun p.

    Like

    1. Hi Tarun, Apologies for late reply. As far as I understand the code, can you use a simple wait statement before the display.

      Like

  4. I get an error when creating the process::status() return variable.
    process::state Pstate; <– “expecting an identifier” error

    Like

    1. Hey George, Can you please show your code snippet about how and where are you declaring the variable. Status returns a ‘state’ kind of variable. The code you showed works fine for me.

      Like

      1. the following is in a task

        task example();

        process::state Pstate; <– This declaration cause an error “expecting an identifier”

        Pstate = process::status();

        endtask

        The simulator is Cadence simvision.

        Like

      2. Two things over here.
        1. You have to get the current process handle to get the status. Thereafter we can get status of any process.
        process::state Pstate;
        process p;
        p = process::self();
        Pstate = p.status();

        The above code works in Synopsys VCS. Please contact your tool vendor for support.

        Like

      3. Thank you for replying.

        I do have the code you’re describing but the declaration of Pstate is where the issue is and I think it must be a vendor simulator issue. I’ll contact them.

        Thank you.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: