Showing posts with label fork. Show all posts
Showing posts with label fork. Show all posts

Thursday, April 20, 2023

System Verilog - Fork, Join

A common question in interviews for System Verilog is .... 

How do you come out of fork-join_none/any if 2 out of the 3 process in fork are complete.

Fork-join_any will wait until any one process is complete.

If you want to wait until any two process are complete, you can use semaphores or static variables inside each process and wait on the semaphore/variable for join_any/join_none statement.


One more questions revolving it is with fork_join.

You have 3 processes, and you need to come out of fork_join when 2 out of 3 process are complete. 

How to achieve this?

One way of doing it is using labels.

Check out....

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class test;
  static int cnt;
  
  task check_fork;
    fork
      begin: p1
        #30;cnt++;
        $display("%t - Process-1 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p3;
            disable p2;
        end
      end
      begin: p2
        #40;cnt++;
        $display("%t - Process-2 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p3;
            disable p1;
        end
      end
      begin: p3
        #10;cnt++;
        $display("%t - Process-3 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p2;
            disable p1;
        end
      end
    join
        $display("%t - Process-Complete cnt:%d",$time,cnt);
  endtask
endclass: test

module top;
  
  test s;
  
  initial begin
    s=new;
    s.check_fork;

  end
endmodule: top

RESULT:

Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Apr 20 11:06 2023
10 - Process-3 cnt: 1
30 - Process-1 cnt: 2
30 - Process-Complete cnt: 2
V C S S i m u l a t i o n R e p o r t
Time: 30 ns
CPU Time: 0.560 seconds; Data structure size: 0.0Mb
Thu Apr 20 11:06:20 2023

Thursday, April 1, 2021

Fork Join_none and SV Objects

 Typically whenever we require to spawn threads using fork join_none and a for loop, we use "automatic int". This is required to pass on the correct value into the threads. Otherwise, the last value in the loop is passed on to all the threads.


What if an object is passed instead of a data_type like int?

In the below code, we have 3 scenarios

1. Using an array of objects and automatic int whilst spawning threads.

2. Using a queue

3. Not having 'automatic int' to guide the array.


CODE:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//==================================================//
// CLASS : DATA_OBJ
// Description :
// containts data_id and data
// 
//==================================================//
class data_obj;
  int data_id;
  string data;
  
  //==================================================//
  // load_val
  // loads data_id and data
  //==================================================//
  function void load_val ( int id, string val);
    data_id = id;
    data    = val;
  endfunction
endclass

//==================================================//
// TEST_CLASS
// Description:
// Contains and array and queue
// Intention is to check the automatic function in 
// SV class
//==================================================//

class test_class;
  
  data_obj obj[3];
  data_obj obj_q[$];
  
  //==================================================//
  // LOAD_OBJ
  // Fills array and queue with data_obj objects
  //==================================================//
  function void load_obj();
    for(int i=0;i <3;i++) begin
      obj[i] = new;
      obj[i].load_val(i,"pavan");
      obj_q.push_back(obj[i]);
    end
  endfunction
  
  //==================================================//
  // SPAWN
  // Uses automatic int approach to load object into
  // print_data function
  // TRY : Try replacing 'j' with 'i'
  //==================================================//
  function void spawn();
    for(int i=0; i<3;i++) begin
      automatic int j=i;
      fork
        print_data(obj[j]);  // Replace J with I and check    
      join_none
    end
  endfunction
  
  //==================================================//
  // POP_SPAWN
  // Simply pops the data into the print_data function
  //==================================================//
  function void pop_spawn();
    for(int i=0; i<3;i++) begin
      fork
        print_data(obj_q.pop_front());      
      join_none
    end
  endfunction
  
  //==================================================//
  // Print_data
  // Prints the data
  //==================================================//
  function void print_data(data_obj obj);
    $display("OBJ ID:%0d VAL:%0s",obj.data_id,obj.data);
  endfunction
  
endclass

//==================================================//
// MODULE: TOP
//==================================================//
module top;

  test_class test_c;
  
  initial begin

    test_c = new;
    test_c.load_obj();
    test_c.spawn();      // Spawn threads using automatic int approach
    test_c.pop_spawn();  // Spawn threads using queue pop approach
    #100ns;
   
  end
endmodule: top


RESULTS:

1. Using an array of objects and automatic int whilst spawning threads.

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:21 2021
OBJ ID:0 VAL:pavan
OBJ ID:1 VAL:pavan
OBJ ID:2 VAL:pavan

 2. Using a queue

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:23 2021
OBJ ID:0 VAL:pavan
OBJ ID:1 VAL:pavan
OBJ ID:2 VAL:pavan

3. Not having 'automatic int' to guide the array.

Compiler version Q-2020.03-SP1-1; Runtime version Q-2020.03-SP1-1; Apr 1 22:24 2021

Error-[NOA] Null object access
testbench.sv, 79
The object at dereference depth 0 is being used before it was
constructed/allocated.
Please make sure that the object is allocated before using it.

#0 in \test_class::print_data at testbench.sv:79
#1 in \test_class::spawn at testbench.sv:57
#2 in top at testbench.sv:95
#3 in top

Constraint to have N elements distributed in M bins

Code to distribute N elements into M bins, you add unique keyword to have each bin will have unique number of elements. class test; param...