0% found this document useful (0 votes)
400 views90 pages

System Verilog Mod 4

The document provides an overview of threads and interprocess communication (IPC) in SystemVerilog, highlighting their roles in enabling parallel execution of testbench components. It discusses various IPC mechanisms such as events, semaphores, and mailboxes, and illustrates thread execution with examples. Key takeaways emphasize the importance of threads for efficient verification and the use of SystemVerilog constructs for synchronization and resource management.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
400 views90 pages

System Verilog Mod 4

The document provides an overview of threads and interprocess communication (IPC) in SystemVerilog, highlighting their roles in enabling parallel execution of testbench components. It discusses various IPC mechanisms such as events, semaphores, and mailboxes, and illustrates thread execution with examples. Key takeaways emphasize the importance of threads for efficient verification and the use of SystemVerilog constructs for synchronization and resource management.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

BANGALORE INSTITUTE OF TECHNOLOGY

System Verilog
(MECV115A)
Course Handling Faculty: Keshava A

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Module - 4

Threads and Interprocess


Communication

2
DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING
BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
1. What are Threads?
• Threads allow parallel execution of multiple processes in a testbench.
• In real hardware, sequential logic updates on clock edges, while combinational logic updates
when inputs change.
• SystemVerilog simulates parallel activities using:
 initial and always blocks
 fork...join constructs
 Testbench components like generators, drivers, monitors, and checkers

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
2. Role of Threads in a Testbench
• Each testbench component runs in its own execution thread.
• The SystemVerilog Scheduler decides which thread runs next.
• The testbench environment consists of multiple blocks running in parallel.

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
3. Testbench Environment Blocks
• Components in a layered testbench:
Generator → Creates stimulus for the DUT.
Agent → Processes and modifies the stimulus.
Driver → Sends the stimulus to the DUT.
Monitor → Captures responses from the DUT.
Checker → Verifies if DUT output matches expected results.
Scoreboard → Keeps track of verification results.

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
4. What is Interprocess Communication (IPC)?
• IPC enables threads to exchange data and synchronize execution.
• Needed because different testbench components must communicate.
• IPC ensures:
 Data Transfer – Between testbench components.
 Synchronization – Ensuring one thread waits for another.
 Resource Management – Prevents multiple threads from using the same resource
simultaneously.

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
5. SystemVerilog IPC Mechanisms

IPC Mechanism Purpose Example


Events Synchronization @event_name;
Semaphores Resource sharing sem.get(1);
Mailboxes Data passing mbx.put(data);

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
6. Mathematical Representation of Parallel Execution
• Execution time of a thread Ti​:

 Where Dj​ is the delay of statement j in thread Ti​.

• Total execution time of multiple threads:

 Ensures all dependent threads finish before proceeding.

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
7. Example SystemVerilog Code for Thread Execution

initial begin
fork
#10 $display("Thread 1 Executing");
#20 $display("Thread 2 Executing");
join
$display("Both threads completed");
end

• fork...join ensures both threads run in parallel.


• Execution resumes only when both threads complete. 9

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Introduction
8. Key Takeaways
 Threads enable parallel execution of testbench components.
 IPC allows communication and synchronization between threads.
 SystemVerilog constructs include events, semaphores, and mailboxes.
 Testbench architecture relies on multiple threads for efficient verification.

10

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


1. Introduction to Threads in SystemVerilog
• Threads allow multiple execution paths to run in parallel.
• SystemVerilog enables thread execution using initial blocks inside program blocks.
• always blocks cannot be used inside program blocks but can be simulated using forever loops
inside initial blocks.

11

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


2. Grouping Statements in SystemVerilog
SystemVerilog provides different ways to group statements:
3. Sequential Execution:
• Uses begin...end.
• Statements execute one after another.
2. Parallel Execution:
• Uses fork...join.
• All statements inside fork...join execute in parallel, and the parent thread waits for all child
threads to finish before continuing.

12

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


3. Using fork...join and begin...end Example:
initial begin
• fork...join runs statements in parallel. $display("@%0d: start fork...join example", $time);
#10 $display("@%0d: sequential after #10", $time);
• begin...end runs statements sequentially. fork
$display("@%0d: parallel start", $time);
#50 $display("@%0d: parallel after #50", $time);
Execution Order: #10 $display("@%0d: parallel after #10", $time);
begin
 fork...join ensures parallel execution. #30 $display("@%0d: sequential after #30", $time);
#10 $display("@%0d: sequential after #10", $time);
 The program waits for all threads to end
join
finish before moving to after join. $display("@%0d: after join", $time);
#80 $display("@%0d: final after #80", $time);
 The longest delay (#50) dictates when
end
the join statement completes.
13

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


3. Using fork...join and begin...end
@0: start fork...join example
@10: sequential after #10
@10: parallel start
@20: parallel after #10
@40: sequential after #30
@50: sequential after #10
@60: parallel after #50
@60: after join
@140: final after #80
14

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


4. Spawning Threads with fork...join_none Example:
• fork...join_none starts new threads but does not initial begin
$display("@%0d: start fork...join_none example",
wait for them to finish. $time);
#10 $display("@%0d: sequential after #10", $time);
• Execution continues immediately after fork
$display("@%0d: parallel start", $time);
fork...join_none. #50 $display("@%0d: parallel after #50", $time);
#10 $display("@%0d: parallel after #10", $time);
Execution Order: begin
#30 $display("@%0d: sequential after #30", $time);
 The after join_none message prints #10 $display("@%0d: sequential after #10", $time);
end
immediately after fork. join_none
$display("@%0d: after join_none", $time);
 All parallel threads continue execution #80 $display("@%0d: final after #80", $time);
end
in the background.
15

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


4. Spawning Threads with fork...join_none
Example:
@0: start fork...join_none example
initial begin
$display("@%0d: start fork...join_none example", @10: sequential after #10
$time);
#10 $display("@%0d: sequential after #10", $time); @10: after join_none
fork
$display("@%0d: parallel start", $time); @10: parallel start
#50 $display("@%0d: parallel after #50", $time);
#10 $display("@%0d: parallel after #10", $time); @20: parallel after #10
begin
#30 $display("@%0d: sequential after #30", $time); @40: sequential after #30
#10 $display("@%0d: sequential after #10", $time);
end @50: sequential after #10
join_none
$display("@%0d: after join_none", $time); @60: parallel after #50
#80 $display("@%0d: final after #80", $time);
@90: final after #80
end
16

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


5. Synchronizing Threads with fork...join_any Example:
• fork...join_any starts multiple threads and waits initial begin
$display("@%0d: start fork...join_any example",
for any one to finish before continuing. $time);
#10 $display("@%0d: sequential after #10", $time);
• Other threads continue running in the background. fork
$display("@%0d: parallel start", $time);
#50 $display("@%0d: parallel after #50", $time);
#10 $display("@%0d: parallel after #10", $time);
Execution Order: begin
#30 $display("@%0d: sequential after #30", $time);
 The after join_any message prints after #10 $display("@%0d: sequential after #10", $time);
end
the first thread completes. join_any
$display("@%0d: after join_any", $time);
 Other threads continue executing in the #80 $display("@%0d: final after #80", $time);
end
background.
17

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


5. Synchronizing Threads with fork...join_any
Example:
@0: start fork...join_any example
initial begin
$display("@%0d: start fork...join_any example", $time); @10: sequential after #10
#10 $display("@%0d: sequential after #10", $time);
fork @10: parallel start
$display("@%0d: parallel start", $time);
#50 $display("@%0d: parallel after #50", $time); @10: after join_none
#10 $display("@%0d: parallel after #10", $time);
begin @20: parallel after #10
#30 $display("@%0d: sequential after #30", $time);
#10 $display("@%0d: sequential after #10", $time); @40: sequential after #30
end
join_any @50: sequential after #10
$display("@%0d: after join_any", $time);
#80 $display("@%0d: final after #80", $time); @60: parallel after #50
end
@90: final after #80
18

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


6. Creating Threads in a Class Example:
class Generator;
• Threads can be created inside SystemVerilog task run(int n);
Packet p;
classes.
fork
• Use fork...join_none inside a class task to run repeat (n) begin
p = new;
independent threads. if (!p.randomize) begin
$display("Packet randomization failed");
$finish;
 The run task starts a thread inside end
transmit(p);
fork...join_none.
end
 The constructor does not start execution, keeping join_none
endtask
the design modular. endclass
19

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


Example:
7. Dynamic Threads program automatic test(busif.TB bus);
• Unlike static threads, which are predefined, task wait_for_tr(Transaction tr);
fork
dynamic threads can be created at runtime. begin
wait (bus.cb.addr != tr.addr);
• Useful in testbenches that handle random $display("@%0d: Addr match %d", $time,
tr.addr);
transactions. end
join_none
endtask
 The wait_for_tr task spawns a thread initial repeat (10) begin
Transaction tr = new;
dynamically. if (!tr.randomize) $finish;
 Multiple threads run independently to match transmit(tr);
wait_for_tr(tr);
transaction addresses. end
endprogram
20

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


8. Automatic Variables in Threads
• If a loop spawns multiple threads, they may overwrite shared variables.
• Using automatic variables ensures each thread keeps its own copy.
Incorrect Example: Correct Example:
initial begin initial begin
for (int j=0; j<3; j++) for (int j=0; j<3; j++)
fork fork
$write(j); // Bug: All threads print final value of j automatic int k = j;
join_none $write(k); // Each thread gets its own k
#0 $display; join_none
end #0 $display;
end
 All threads print the final value of j (3, 3, 3)
 Each thread now correctly prints 0, 1, 2.
instead of 0, 1, 2.
21

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


Example:
9. Disabling a Single Thread parameter TIME_OUT = 1000;
• Sometimes, a thread needs to be stopped before it
task wait_for_tr(Transaction tr);
completes execution. fork
begin
• The disable statement is used to stop a single // Wait for response or timeout
fork : timeout_block
thread. wait (bus.cb.addr != tr.addr);
#TIME_OUT $display("@%0d: Error: timeout",
• Example: A thread is waiting for a transaction, but $time);
join_any
if it takes too long, it should timeout. disable timeout_block;

$display("@%0d: Addr match %d", $time, tr.addr);


end
join_none
endtask

22

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


9. Disabling a Single Thread
Example:
parameter TIME_OUT = 1000;  The outer fork...join_none allows parallel

task wait_for_tr(Transaction tr); execution.


fork  The inner fork...join_any waits for either the
begin
// Wait for response or timeout
correct bus address or a timeout.
fork : timeout_block
wait (bus.cb.addr != tr.addr);  If the address match happens first, disable
#TIME_OUT $display("@%0d: Error: timeout",
$time); timeout_block stops the timeout thread.
join_any
disable timeout_block;  If the timeout happens first, an error message is

$display("@%0d: Addr match %d", $time, tr.addr); printed.


end
join_none
endtask 23

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


Example:
10.Disabling Multiple Threads initial begin
• The disable fork statement is used to wait_for_tr(tr0); // Spawn thread 0

stop all child threads. // Create a thread to limit the scope of disable
fork
• Be careful: It stops all threads spawned begin
wait_for_tr(tr1); // Spawn thread 1
from the current fork, which may be too fork // Spawn another forked thread (Thread 2)
wait_for_tr(tr2);
many! join
#500 disable fork; // Stops threads 1 & 2, but leaves thread 0
• Solution: Use a labeled block to control end
join
which threads are disabled. end

24

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


10.Disabling Multiple Threads
Example:  Thread 0 runs independently.
initial begin
wait_for_tr(tr0); // Spawn thread 0  Thread 1 spawns another thread (Thread 2).
 disable fork; stops only threads 1 & 2, but not thread
// Create a thread to limit the scope of disable
fork 0.
begin
wait_for_tr(tr1); // Spawn thread 1
fork // Spawn another forked thread (Thread 2)
wait_for_tr(tr2);
join
#500 disable fork; // Stops threads 1 & 2, but leaves thread 0
end
join
end

25

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


11.Using a Label to Disable Specific Threads
• Instead of stopping all forked threads, you can label a group of threads and disable only those.
Example:
initial begin
wait_for_tr(tr0); // Spawn thread 0

begin : threads_1_2
wait_for_tr(tr1); // Spawn thread 1
wait_for_tr(tr2); // Spawn thread 2
end

// Stop only threads 1 & 2


#(TIME_OUT/2) disable threads_1_2;
end

 Instead of stopping all threads, only the labeled group (threads_1_2) is stopped.
 Thread 0 keeps running. 26

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


12.Waiting for All Spawned Threads
• Sometimes, you want to ensure all threads finish before moving forward.
• Use wait fork; to pause execution until all spawned threads complete.
Example Code: Using wait fork
task run_threads;
... // Create transactions

wait_for_tr(tr1); // Spawn thread 1  All spawned threads (tr1, tr2, tr3) must complete
wait_for_tr(tr2); // Spawn thread 2 before continuing.
wait_for_tr(tr3); // Spawn thread 3  wait fork; ensures no unfinished thread is left behind.
... // Do some other work

// Now wait for the above threads to complete


wait fork;
endtask
27

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


13.Summary of Key Thread Control Techniques
Concept Method Usage
Run parallel threads fork...join Waits for all threads to finish
Run threads in background fork...join_none Parent thread continues execution
Wait for any thread to finish fork...join_any Resumes execution after first thread finishes
Stop a single thread disable thread_label; Stops a specific running thread
Stop multiple threads disable fork; Stops all child threads of the current thread
Wait for all spawned threads wait fork; Ensures all threads finish before moving
forward

28

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Working with Threads


14.Key Takeaways
 fork...join ensures parallel execution of threads.
 Dynamic threads can be created at runtime.
 Use automatic variables to avoid shared-memory issues.
 Synchronization can be handled using fork...join_any and fork...join_none.
 fork...join, fork...join_none, and fork...join_any provide different levels of parallel execution
control.
 disable allows stopping specific threads or all child threads using disable fork;.
 wait fork; ensures that all threads finish before continuing execution.
 Using labels (begin : label_name ... end) provides better control over which threads to stop.
29

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


1. Introduction to Interprocess Communication (IPC)
• In a testbench, multiple threads run in parallel.
• These threads need to synchronize and exchange data to function properly.
• IPC ensures:
Synchronization: Threads coordinate execution (e.g., a checker waits for a generator to finish).
Data Exchange: Passing data between different threads (e.g., transactions between a generator
and a driver).
Resource Management: Ensures only one thread accesses a shared resource at a time.

30

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


2. Why is IPC Needed?
• Example Scenario:
A generator creates stimulus and passes it to the agent.
The agent processes the data and sends it to the driver.
The checker must wait until all stimulus has been applied to the DUT.
• Without proper synchronization, threads may execute in an unexpected order, leading to errors.

31

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


3. IPC Mechanisms in SystemVerilog
• Events: Used for thread synchronization.
• Semaphores: Used for mutual exclusion (ensures one thread accesses a resource at a time).
• Mailboxes: Used for passing data between threads.
• Classic Constructs:
@ event control (blocking execution until an event occurs).
wait statement (waiting for a condition to become true).

32

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


Example Code: Event-Based Synchronization
4. Events in SystemVerilog event e1, e2;
• An event is a synchronization initial begin
$display("@%0d: 1: before trigger", $time);
mechanism that allows one thread to -> e1; // Triggers event e1
@e2; // Waits for event e2
wake up another thread. $display("@%0d: 1: after trigger", $time);
end
• Similar to a phone call:
initial begin
One thread waits for a call $display("@%0d: 2: before trigger", $time);
-> e2; // Triggers event e2
(@event_name). @e1; // Waits for event e1
$display("@%0d: 2: after trigger", $time);
Another thread triggers the event
end
(-> event_name).  Problem: If one thread misses the event (e.g., the trigger
happens before the wait), the thread gets stuck forever.
 Solution: Use event triggered function. 33

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


Example Code: Waiting for an Event
5. Waiting for an Event Trigger event e1, e2;
• Problem: If an event is triggered initial begin
$display("\n@%0d: 1: before trigger", $time);
before a thread waits for it, the -> e1; // Triggers event
wait (e2.triggered); // Non-blocking wait for event e2
event is missed. $display("@%0d: 1: after trigger", $time);
end
• Solution: Use the triggered
initial begin
function, which checks if an event $display("@%0d: 2: before trigger", $time);
-> e2;
has been triggered. wait (e1.triggered); // Non-blocking wait for event e1
$display("@%0d: 2: after trigger", $time);
• Unlike @event, it does not block end
execution.
 No thread gets stuck because wait (event.triggered);
checks if the event happened before waiting.
34

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


6. Passing Events
• In SystemVerilog, events are objects and can be passed around between tasks and classes.
• This allows one module to trigger an event that another module is waiting for.
Example Code: Passing Events to a Constructor program automatic test;
class Generator; event gen_done;
event done; Generator gen;
function new(event done); // Constructor accepts an event
this.done = done; initial begin
endfunction gen = new(gen_done); // Pass event to generator
gen.run;
task run; wait(gen_done.triggered); // Wait until event is triggered
fork end
begin endprogram
... // Create transactions
-> done; // Triggers event when task is complete  Generator triggers done event, and the testbench waits for
end
it before continuing execution.
join_none
endtask  Useful for complex testbenches where different modules
endclass
must coordinate execution. 35

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


Example Code: Waiting for Multiple Threads Using Events
7. Waiting for Multiple Events event done[N_GENERATORS];
• If multiple threads must complete before initial begin
foreach (gen[i]) begin
proceeding, we need to wait for multiple gen[i] = new; // Create N generators
gen[i].run; // Start them running
events.
end
• Problem: Threads may finish out of order.
// Wait for all generators to finish
• Solution: Use wait fork; or keep track of foreach (gen[i])
fork
event triggers. automatic int k = i;
wait (done[k].triggered);
join_none
 Each thread waits for its corresponding
event to be triggered. wait fork; // Ensures all spawned threads complete
end
 wait fork; ensures all events are triggered
before execution proceeds. 36

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


Example Code: Counting Completed Threads
8. Alternative Method: Counting Event Triggers event done[N_GENERATORS];
• Instead of waiting for individual events, we can count initial begin
foreach (gen[i]) begin
how many have completed. gen[i] = new;
gen[i].run;
end
// Track completed events
foreach (gen[i])
fork
automatic int k = i;
begin
wait (done[k].triggered);
done_count++;
 Threads update a done_count variable when they end
complete. join_none
 The testbench waits until done_count matches the wait fork; // Ensures all the triggers complete
number of generators. end 37

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


9. Summary of IPC Mechanisms
IPC Mechanism Purpose Key Example
Events (@event) Synchronization -> event_name;
Triggered Function Avoids missing events wait (event.triggered);
Passing Events Modules share event handles function new(event done);
Waiting for Multiple Events Ensures all tasks complete wait fork;
Counting Event Triggers Tracks completion manually done_count++;

38

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Interprocess Communication (IPC)


9. Key Takeaways
 Events allow threads to communicate and synchronize execution.
 Using @ event can cause missed signals; use wait (event.triggered); instead.
 Passing events as objects helps decouple modules in a testbench.
 For multiple threads, use wait fork; or track event triggers manually.

39

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
1. Introduction to Events
• Events in SystemVerilog are used for thread synchronization.
• They allow one thread to trigger an event while another thread waits for it.
• Similar to a phone call where:
One person waits for a call (@event_name;).
Another person triggers the call (-> event_name;).

40

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
2. Blocking on the Edge of an Event
• How does a thread wait for an event?
Use @event_name; → Blocks execution until the event occurs.
• How does a thread trigger an event?
Use -> event_name; → Triggers the event and unblocks any waiting thread.
• Potential Issue:
If an event is triggered before a thread starts waiting, the waiting thread misses the event and
gets stuck.

41

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
2. Blocking on the Edge of an Event
Example Code: Blocking on an Event
event e1, e2;
initial begin
$display("@%0d: 1: before trigger", $time);
-> e1; // Trigger event e1
@e2; // Wait for event e2 Problem:
$display("@%0d: 1: after trigger", $time); • If e2 is triggered before @e2 starts waiting, the
end waiting thread misses the event and hangs.
initial begin
$display("@%0d: 2: before trigger", $time); Solution:
-> e2; // Trigger event e2 • Use triggered function (explained next).
@e1; // Wait for event e1
$display("@%0d: 2: after trigger", $time);
end

42

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
Example Code: Waiting for an Event with triggered
3. Waiting for an Event Trigger event e1, e2;
• Problem with @event:
initial begin
If an event occurs before a thread waits $display("\n@%0d: 1: before trigger", $time);
-> e1;
for it, the waiting thread misses it. wait (e2.triggered); // Non-blocking wait for event e2
$display("@%0d: 1: after trigger", $time);
• Solution: Use triggered function end

It checks if an event has been initial begin


$display("@%0d: 2: before trigger", $time);
triggered, even in the current time step. -> e2;
wait (e1.triggered); // Non-blocking wait for event e1
$display("@%0d: 2: after trigger", $time);
Advantages of triggered: end
• Prevents threads from missing events.
• Works in zero-time simulation steps where
@event might fail. 43

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY
Events
4. Passing Events Between Threads
• In SystemVerilog, events are objects that can be passed between tasks or classes.
• Allows different modules to communicate using shared event handles.
Example Code: Passing Events in a Constructor program automatic test;
class Generator; event gen_done;
event done; Generator gen;
function new(event done); // Constructor accepts an event
this.done = done; initial begin
endfunction gen = new(gen_done); // Pass event to generator
task run; gen.run;
fork wait(gen_done.triggered); // Wait until event is
begin triggered
... // Create transactions end
-> done; // Triggers event when task is complete endprogram
end Key Benefit:
join_none • Allows the Generator class to signal when it completes
endtask execution.
endclass • The Test program waits for this signal before proceeding.
44

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY
Events
5. Waiting for Multiple Events
• Scenario:
A testbench may need to wait for multiple events before proceeding.
• Approach 1: Using wait fork;
Waits for all spawned threads to complete.
• Approach 2: Using a loop to wait for each event
But this only works if events occur in order.
• Solution: Create a separate thread that waits for each event.

45

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY
Events
5. Waiting for Multiple Events
Example Code: Waiting for Multiple Threads with wait fork;
event done[N_GENERATORS];

initial begin
foreach (gen[i]) begin
gen[i] = new; // Create N generators
gen[i].run; // Start them running
end Ensures:
• Each thread waits for its corresponding
// Wait for all generators to finish
foreach (gen[i]) event to be triggered.
fork • The testbench proceeds only after all
automatic int k = i; events have occurred.
wait (done[k].triggered);
join_none

wait fork; // Ensures all spawned threads complete


end
46

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
6. Counting Event Triggers Instead of Waiting
• Instead of waiting on individual events, we can count the number of events triggered.
• Useful when we don’t care about the order of event completion.
Example Code: Counting Completed Events begin
event done[N_GENERATORS]; wait (done[k].triggered);
done_count++;
initial begin end
foreach (gen[i]) begin join_none
gen[i] = new;
gen[i].run; wait fork; // Ensures all the triggers complete
end end

// Track completed events


foreach (gen[i])
Works when:
fork • The order of event completion doesn’t matter.
automatic int k = i; • Instead of waiting, we track how many threads have
finished. 47

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
7. Alternative: Using a Static Thread Counter
• Another way to track completion is using a static variable in a class.
• Instead of events, we count active threads.
Example Code: Using a Static Counter Instead of Events Generator gen[N_GENERATORS];
class Generator;
static int thread_count = 0; initial begin
// Create N generators
task run; foreach (gen[i])
thread_count++; // Start another thread gen[i] = new;
fork
begin // Start them running
... // Perform thread work foreach (gen[i])
thread_count--; // Decrement thread count when done gen[i].run;
end
join_none // Wait for the generators to complete
endtask wait (gen[0].thread_count == 0);
endclass end 48

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
7. Alternative: Using a Static Thread Counter
Example Code: Using a Static Counter Instead of Events Generator gen[N_GENERATORS];
class Generator;
static int thread_count = 0; initial begin
// Create N generators
task run; foreach (gen[i])
thread_count++; // Start another thread gen[i] = new;
fork
begin // Start them running
... // Perform thread work foreach (gen[i])
thread_count--; // Decrement thread count when done gen[i].run;
end
join_none // Wait for the generators to complete
endtask wait (gen[0].thread_count == 0);
endclass end

Key Benefit:
• No need for separate events for each thread.
• The testbench just waits until thread_count == 0. 49

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
8. Summary of Event-Based Synchronization

Technique Purpose Key Example


@ event Synchronization @e1;
triggered function Prevent missed events wait (e1.triggered);
Passing Events Share event handles function new(event done);
Waiting for Multiple Events Synchronization wait fork;
Counting Event Triggers Track completion done_count++;
Using Thread Counter Alternative to events wait (thread_count == 0);

50

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Events
9. Key Takeaways
 Events synchronize threads in testbenches.
 @event blocks execution, while ->event triggers it.
 Use triggered function to prevent missed events.
 For multiple threads, use wait fork; or count triggers manually.

51

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
1. Introduction to Semaphores
• A semaphore is a synchronization mechanism used to control access to a shared resource.
• Works like a key system, where a process must obtain a key before using a resource.
• Example:
Imagine you and your spouse share one car. Only the person who has the key can drive it.
The key acts as a semaphore, ensuring only one person accesses the car at a time.
• Why Semaphores?
In a testbench, multiple threads may need exclusive access to a shared resource (e.g., a bus).
Ensures mutual exclusion so only one thread at a time accesses the resource.

52

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
2. How Semaphores Work in SystemVerilog
• Semaphores are objects in SystemVerilog.
• Operations:
 new(N): Creates a semaphore with N keys (permits).
 get(K): Acquires K keys (blocks if unavailable).
 put(K): Releases K keys, making them available.
 try_get(K): Tries to acquire K keys (non-blocking).

53

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
3. Basic Semaphore Operations
• Semaphores are declared as objects and must be instantiated using new().
• If a thread requests a key when none are available, it blocks.
Example Code: Controlling Access to a Bus task sequencer;
program automatic test; repeat($urandom%10) // Random wait, 0-9 cycles
semaphore sem; // Declare semaphore @bus.cb;
initial begin sendTrans; // Execute the transaction
sem = new(1); // Allocate with 1 key endtask
fork
sequencer; // Spawn two threads that both task sendTrans;
sequencer; // perform bus transactions sem.get(1); // Get the key to the bus
join @bus.cb; // Drive signals onto the bus
end bus.cb.addr <= t.addr;
...
sem.put(1); // Release the key when done
endtask
endprogram 54

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
3. Basic Semaphore Operations
Example Code: Controlling Access to a Bus task sequencer;
program automatic test; repeat($urandom%10) // Random wait, 0-9 cycles
semaphore sem; // Declare semaphore @bus.cb;
initial begin sendTrans; // Execute the transaction
sem = new(1); // Allocate with 1 key endtask
fork
sequencer; // Spawn two threads that both task sendTrans;
sequencer; // perform bus transactions sem.get(1); // Get the key to the bus
join @bus.cb; // Drive signals onto the bus
end bus.cb.addr <= t.addr;
...
sem.put(1); // Release the key when done
Execution Flow: endtask
1. Each thread tries to access the bus. endprogram
2. The first thread acquires the semaphore key and
starts the transaction.
3. The second thread blocks until the key is released. 55

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
4. Using Semaphores with Multiple Keys
• A semaphore can have multiple keys to allow multiple threads to access a resource.
• Example Scenario:
 A testbench simulates a system with multiple buses.
 Each bus requires a key, and multiple buses can be used at once.

56

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
5. Potential Problems with Semaphores
Issue 1: Returning More Keys Than Taken
• If a thread puts back more keys than it took, the system loses control over resource access.
Example Mistake:
sem.get(1);
sem.put(2); // ERROR: More keys returned than taken!

Issue 2: FIFO Blocking Order


• If a thread requests multiple keys, but only one is available, it blocks completely.
• Problem Example:
 One thread requests 2 keys, but only 1 is available.
 A second thread requests 1 key, but the first thread is blocking access.
 Result: The second thread is blocked, even though a key is available. 57

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
5. Potential Problems with Semaphores
Solution:
• Modify the algorithm to prioritize smaller requests over large ones.
• Custom logic can manage key allocation dynamically.

58

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
6. Alternative Approach: Custom Synchronization
• If FIFO blocking is an issue, a custom resource manager can be built.
• Example:
 A restaurant seating system prioritizes smaller parties if a small table is available.
 Similar logic can be implemented in a testbench for shared resource management.

59

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
7. Summary of Semaphore Operations

Operation Description

new(N) Creates a semaphore with N keys.

get(K) Acquires K keys (blocks if unavailable).

put(K) Releases K keys (must not exceed the initial limit).

try_get(K) Tries to acquire K keys (non-blocking).

FIFO Blocking Threads queue in order when waiting for keys.

60

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Semaphores
8. Key Takeaways
 Semaphores ensure exclusive access to shared resources.
 get(K) blocks execution if insufficient keys are available.
 Returning extra keys leads to resource mismanagement.
 FIFO order can cause blocking issues if larger requests take priority.
 Custom solutions can prioritize smaller requests when needed.

61

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
1. Introduction to Mailboxes
• Mailboxes in SystemVerilog provide a way for threads to communicate by passing data
asynchronously.
• Concept:
 A producer thread puts data into a mailbox.
 A consumer thread retrieves data from the mailbox.
• Why Use Mailboxes?
 Avoids direct function calls between objects, improving testbench modularity.
 Allows asynchronous execution (the sender and receiver operate independently).

62

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
2. How Mailboxes Work in SystemVerilog
• Mailboxes are objects and must be instantiated using new().
• Basic Operations:
 put(value): Adds data to the mailbox (blocks if full).
 get(variable): Retrieves data from the mailbox (blocks if empty).
 peek(variable): Reads data without removing it.
 try_get(variable): Tries to retrieve data but does not block if empty.

63

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
3. Mailbox Example in a Testbench
• Scenario: A generator produces transactions and passes them to a driver using a mailbox.
Example Code: Generator-Driver Communication Using a Mailbox
program mailbox_example(bus_if.TB bus, ...); class Driver; mailbox mbx; // Declare mailbox
Transaction tr; Generator gen;
class Generator; mailbox mbx; Driver drv;
Transaction tr;
mailbox mbx; function new(mailbox mbx); initial begin
this.mbx = mbx; mbx = new;
function new(mailbox mbx); endfunction gen = new(mbx);
this.mbx = mbx; drv = new(mbx);
endfunction task run; fork
repeat (10) begin gen.run(); // Start generator
task run; mbx.get(tr); // Fetch transaction from drv.run(); // Start driver
repeat (10) begin mailbox join
tr = new; @(posedge busif.cb.ack); end
assert(tr.randomize); bus.cb.kind <= tr.kind; endprogram
mbx.put(tr); // Send transaction to ...
mailbox end
end endtask
endtask endclass
endclass 64

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
3. Mailbox Example in a Testbench
Example Code: Generator-Driver Communication Using a Mailbox
program mailbox_example(bus_if.TB bus, ...); class Driver; mailbox mbx; // Declare mailbox
Transaction tr; Generator gen;
class Generator; mailbox mbx; Driver drv;
Transaction tr;
mailbox mbx; function new(mailbox mbx); initial begin
this.mbx = mbx; mbx = new;
function new(mailbox mbx); endfunction gen = new(mbx);
this.mbx = mbx; drv = new(mbx);
endfunction task run; fork
repeat (10) begin gen.run(); // Start generator
task run; mbx.get(tr); // Fetch transaction from mailbox drv.run(); // Start driver
repeat (10) begin @(posedge busif.cb.ack); join
tr = new; bus.cb.kind <= tr.kind; end
assert(tr.randomize); ... endprogram
mbx.put(tr); // Send transaction to end
mailbox endtask How It Works:
end endclass
• The generator creates and sends transactions to
endtask
endclass the mailbox.
• The driver retrieves transactions from the
mailbox and applies them to the DUT. 65

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
4. Bounded vs. Unbounded Mailboxes
• Unbounded Mailbox: Can hold unlimited messages.
 Default behavior when no size is specified (new()).
• Bounded Mailbox: Has a fixed size.
 If full, put() blocks until space is available.
 Ensures the producer doesn’t generate data faster than the consumer can process it.

66

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
4. Bounded vs. Unbounded Mailboxes
Example Code: Bounded Mailbox

program automatic bounded; // Consumer How It Works:


mailbox mbx; repeat(3) begin • The producer puts 3 values
int j;
initial begin #1ns mbx.get(j); into the bounded mailbox.
mbx = new(1); // Size = 1 (Bounded) $display("@%0d: Consumer: got • Since size = 1, the producer
fork %0d", $time, j);
// Producer end blocks after putting the first
for (int i=1; i<4; i++) begin join_any
value until the consumer
$display("@%0d: Producer: putting end
%0d", $time, i); endprogram retrieves it.
mbx.put(i);
• The consumer retrieves data
$display("@%0d: Producer: put(%0d)
done", $time, i); with a 1ns delay.
end
67

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
5. Synchronization Issues with Unsynchronized Threads
• If producer and consumer run at different speeds, the producer may get ahead of the consumer.
• Problem: The producer fills the mailbox before the consumer can process data.

Example Code: Unsynchronized Producer-Consumer mailbox mbx;


Producer p;
program automatic unsynchronized; class Consumer; Consumer c;
task run; initial begin
class Producer; int i; mbx = new;
task run; repeat (3) begin p = new;
for (int i=1; i<4; i++) begin mbx.get(i); c = new;
$display("Producer: before put(%0d)", $display("Consumer: after get(%0d)", i); fork
i); end p.run;
mbx.put(i); endtask c.run;
end endclass join
endtask end
endclass endprogram 68
DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING
BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
5. Synchronization Issues with Unsynchronized Threads
Example Code: Unsynchronized Producer-Consumer
program automatic unsynchronized; class Consumer; mailbox mbx;
task run; Producer p;
class Producer; int i; Consumer c;
task run; repeat (3) begin initial begin
for (int i=1; i<4; i++) begin mbx.get(i); mbx = new;
$display("Producer: before put(%0d)", $display("Consumer: after get(%0d)", i); p = new;
i); end c = new;
mbx.put(i); endtask fork
end endclass p.run;
endtask c.run;
endclass join
Issue: end
endprogram
• The producer fills the mailbox quickly, while the consumer retrieves data slowly.
• The mailbox may overflow, causing unexpected blocking. 69

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
6. Using Events for Producer-Consumer Synchronization
• Solution: Use events to signal when the consumer has finished processing a transaction.
Example Code: Synchronizing Producer and Consumer with an Event
program automatic mbx_evt; class Consumer;
event handshake; task run;
int i;
class Producer; repeat (3) begin
task run; mbx.get(i);
for (int i=1; i<4; i++) begin $display("Consumer: after get(%0d)",
$display("Producer: before put(%0d)", i);
i); ->handshake; // Signal producer
mbx.put(i); end
@handshake; // Wait for consumer endtask
before next put endclass
$display("Producer: after put(%0d)", i); endprogram
end
endtask 70
endclass
DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING
BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
6. Using Events for Producer-Consumer Synchronization
Example Code: Synchronizing Producer and Consumer with an Event
program automatic mbx_evt; class Consumer;
event handshake; task run; How It Works:
int i; • The producer waits for an
class Producer; repeat (3) begin
task run; mbx.get(i); event before putting
for (int i=1; i<4; i++) begin $display("Consumer: after get(%0d)", another transaction.
$display("Producer: before put(%0d)", i);
i); ->handshake; // Signal producer • The consumer triggers the
mbx.put(i); end event after retrieving each
@handshake; // Wait for consumer endtask
before next put endclass transaction.
$display("Producer: after put(%0d)", i); endprogram • Result: The producer
end
endtask doesn’t get ahead of the
endclass consumer.
71

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
7. Alternative Synchronization Methods
8. Using a Second Mailbox:
• Instead of using an event, the consumer sends acknowledgment messages via a second
mailbox.
2. Using a Semaphore:
• The producer gets a semaphore key before putting data, and the consumer releases the key
after consuming it.

72

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
8. Summary of Mailbox-Based Communication

Feature Description
Unbounded Mailbox Holds unlimited transactions.
Bounded Mailbox Has a fixed size (blocks producer if full).
put(value) Adds a value to the mailbox (blocks if full).
get(variable) Retrieves a value from the mailbox (blocks if empty).
Synchronization Issue Producer may generate data faster than the consumer can process it.
Solution 1 Use events to coordinate producer and consumer execution.
Solution 2 Use a second mailbox to send acknowledgments.

73

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Mailboxes
9. Key Takeaways
 Mailboxes enable asynchronous communication between threads.
 Bounded mailboxes prevent unbounded memory usage but can block producers.
 Synchronization issues arise if producers run faster than consumers.
 Use events or a second mailbox to ensure correct execution order.

74

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


1. Introduction to Testbench with Threads and IPC
• Modern verification environments use multiple independent threads that interact using
Interprocess Communication (IPC) techniques.
• Testbench Components:
 Generator – Produces stimulus.
 Agent – Transfers data from the generator to the driver.
 Driver – Applies stimulus to the DUT.
 Monitor – Observes DUT output.
 Checker – Verifies correctness of DUT output.
 Scoreboard – Tracks pass/fail results.
75

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


1. Introduction to Testbench with Threads and IPC
• Why Use Threads and IPC?
 Enables concurrent execution of verification tasks.
 Uses mailboxes, semaphores, and events for synchronization.

76

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


2. Basic Transactor in a Testbench
• A transactor acts as a middle layer between the Generator and Driver.
• Purpose:
 Collects transactions from the generator.
 Processes the transactions.
 Passes them to the driver.

77

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


2. Basic Transactor in a Testbench
Example Code: Transactor
Implementation
class Agent; task run;
forever begin
How It Works:
mailbox gen2agt, agt2drv; // Get transaction from upstream block • The generator puts transactions into
Transaction tr; gen2agt.get(tr);
gen2agt.
function new(mailbox gen2agt, agt2drv); // Do some processing
this.gen2agt = gen2agt; • The agent retrieves, processes, and
this.agt2drv = agt2drv; // Send it to downstream block passes them to agt2drv.
endfunction agt2drv.put(tr);
end • The driver retrieves transactions from
function build; endtask
// Empty for now agt2drv and applies them to the DUT.
endfunction task wrapup;
// Empty for now
endtask

endclass
78

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


3. Environment Class
• The Environment class is the top-level component of the testbench.
• It Instantiates and Connects: class Environment;
How It Works:
 Generator Generator gen; • The environment class
Agent agt;
 Agent Driver drv; initializes IPC mechanisms
Monitor mon;
Checker chk; (mailboxes, events, etc.).
 Driver Example Code: Scoreboard scb; • All testbench components are
Environment Class Config cfg;
 Monitor mailbox gen2agt, agt2drv, mon2chk; instantiated and linked.
 Checker extern function new; • Synchronization between
extern function void gen_cfg;
 Scoreboard extern function void build;
components is handled using
extern task run; mailboxes.
extern task wrapup;
endclass
79

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


4. Initializing the Testbench Example Code: Initialization Functions
• The Environment class contains function Environment::new;
// Initialize mailboxes
functions that: gen2agt = new; Key Operations:
agt2drv = new;
 Create objects. mon2chk = new; • Mailboxes are created for

 Build the testbench. // Initialize transactors communication between


gen = new(gen2agt);
components.
 Run the test sequence. agt = new(gen2agt, agt2drv);
drv = new(agt2drv); • Generator, Agent, Driver,
 Wrap up at the end. mon = new(mon2chk);
chk = new(mon2chk); Monitor, Checker, and
scb = new;
Scoreboard are instantiated.
cfg = new;
endfunction

function void Environment::gen_cfg;


assert(cfg.randomize);
endfunction 80

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


5. Running the Testbench
• The run task starts execution for all components simultaneously using fork...join.
Example Code: Running the Testbench

task Environment::run;
fork
gen.run(run_for_n_trans);
How It Works:
agt.run;
drv.run; • All testbench components run in parallel.
mon.run;
• fork...join ensures that the test completes only after all components finish
chk.run;
scb.run(run_for_n_trans); execution.
join
endtask

81

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


6. Wrapping Up the Testbench
• The wrapup task stops all components and finalizes results.
Example Code: Wrap-Up
Function
task Environment::wrapup;
fork
gen.wrapup;
agt.wrapup; Purpose:
drv.wrapup; • Ensures all components terminate
mon.wrapup;
chk.wrapup; properly.
scb.wrapup; • Collects final test results.
join
endtask

82

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


7. Writing the Top-Level Test Program
• The test program instantiates and runs the environment.
Example Code: Basic Test Program

program automatic test;


How It Works:
Environment env; 1. Creates an instance of the Environment class.
2. Generates a test configuration.
initial begin
env = new; 3. Builds the testbench (creating objects, connecting components).
env.gen_cfg;
4. Runs the test (forks all components).
env.build;
env.run; 5. Wraps up execution and records results.
env.wrapup;
end
endprogram
83

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


8. Summary

Step Description
Create Instantiates all testbench components.
Environment
Initialize IPC Creates mailboxes for communication.
Build Testbench Instantiates and connects components.
Run Test Uses fork...join to execute threads.
Wrap Up Ensures all components terminate correctly.

84

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Building a Testbench with Threads and IPC


9. Key Takeaways
 Testbenches use multiple threads for parallel execution.
 Mailboxes, events, and semaphores enable synchronization.
 The Environment class manages the testbench.
 The test runs using fork...join, ensuring all components complete before finishing.
 A wrap-up function ensures clean termination.

85

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Conclusion
1. Summary of Threads and IPC in SystemVerilog
• SystemVerilog provides advanced multi-threading capabilities for testbenches.
• Threads (Processes) allow concurrent execution of different tasks.
• Interprocess Communication (IPC) enables efficient data exchange and synchronization
between threads.

86

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Conclusion
2. Key Topics Covered in the Chapter
Concept Description
Threads Enable parallel execution of processes.
fork...join Runs multiple threads in parallel.
fork...join_none Starts threads but does not wait for completion.
fork...join_any Waits for any one thread to complete.
Disabling Threads Stops one or more running threads dynamically.
Waiting for Threads Ensures all spawned threads complete execution.
Events Synchronize threads using triggers.
Semaphores Ensure mutual exclusion for shared resources.
Mailboxes Facilitate data exchange between processes.

87

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Conclusion
3. Importance of Using Threads in Verification
• Parallel Execution:
 Allows different testbench components (generator, driver, monitor, checker) to operate
simultaneously.
• Synchronization:
 Ensures that different parts of the testbench communicate effectively without race conditions.
• Scalability:
 Enables complex, large-scale verification environments where multiple testbench elements
need to run concurrently.

88

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Conclusion
4. Choosing the Right IPC Mechanism
• Use fork...join when all threads must complete before continuing.
• Use fork...join_none when threads should run in the background.
• Use fork...join_any when execution should proceed after any thread completes.
• Use Events (@event, triggered) for thread synchronization.
• Use Semaphores for resource access control in testbenches.
• Use Mailboxes to pass data asynchronously between testbench components.

89

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING


BANGALORE INSTITUTE OF TECHNOLOGY

Conclusion
5. Final Takeaways
 SystemVerilog’s multi-threading capabilities allow for highly efficient and flexible testbenches.
 IPC mechanisms ensure testbench components operate synchronously without conflicts.
 Choosing the right technique (forking, events, semaphores, mailboxes) depends on the specific
testbench requirement.
 Proper thread management leads to faster, more scalable, and modular testbenches.

90

DEPARTMENT OF ELECTRONICS AND COMMUNICATION ENGINEERING

You might also like