Concurrency

SungchulCHA·2024년 8월 29일
0

System Verilog

목록 보기
3/6

Creating Concurrent Threads

int a, b, c;                  // parent variables
fork
  [fork local declarations]  // visible to all child threads
  statement0;				 // child thread 1
  statement1;                // child thread 2
  begin                      // child thread 3
    statement2;
    statement3;              // statement1 and statement2 execute sequentially
  end
join | join_any | join_none

statement4;

fork-join 안에서 begin-end로 묶인 statements들은 순서대로 동작하는 single concurrent child thread

join : Child threads execute and all child threads must complete before statement4 is executed

join_any : Child threads execute and one child thread must complete before statement4 is executed. Other child threads continue to run.

join_none : Child threads are queued, statement4 executes. Child threads not executed until parent thread encounters a blocking statement or completes.

Blocking Statement

  • Thread executes until it finishes or a blocking statement is encountered

  • 실행중인 쓰레드가 blocking statement 만나면 It is queued and a queued ready thread executes

  • Examples

@(rtr_io.cb);
wait (var_a == 1);
#10;
join_any
join
  • READY - to be executed at current simulation time
  • WAIT - blocked from execution until wait condition is met

Warning!

  • advance the clock!
a = 0;
fork
  begin
    while ( a != 5 )
      if ( $time > MAX_TIME )
        $finish;
      else
        @(bus.cb);
  end
  begin
    repeat(5) @rtr_io.cb;
    bus.cb.reg <= 1'b1;
    a = 5;
  end
join

첫 쓰레드에 else 구문이 없으면 첫 쓰레드에는 시간 베이스가 없음.
두번째 쓰레드는 rtr_io.cb라는 BA가 있음.
그래서 첫 쓰레드는 무한루프 돎

  • Waiting for Child Threads
program automatic test();
  initial begin
    for (int i = 0; i < 16; i++)
      send(i);
    wait fork;
  end
  task send(int j);
    fork
      begin
        $display("Driving port %0d", j);
        #1ns;
      end
    join_none
  endtask: send
endprogram: test

wait 없으면 0ns에서(endprogram 만나서) 바로 끝남

  • Local Variable
program automatic test;
  initial begin
    for (int i = 0; i < 16; i++) begin
      fork
        int index = i;
        send(index);
      join_none
    end
    wait fork;
  end
  task send(int j);
    $display("Driving port %0d", j);
    #1ns;
  endtask: send
endprogram: test

index 없으면 i를 공유해서됨i++된 16만 출력됨

Watch-Dog Timer

task recv();
  fork
    begin: frameo_n_neg
      wait (rtr_io.cb.frame_n[7] !== 1'b0);
      @(rtr_io.cb iff(rtr_io.cb.frameo_n[7] === 1'b0));
    end
    begin: timer
      repeat(1000) @(rtr_io.cb);
      $display("Timed out!");
      $finish;
    end
  join_any
  
  disable fork;  // 모든 fork 종료 가능성
  get_payload();
endtask
task recv();
  fork begin
    fork: recv_wd_timer
      begin: frameo_n_neg
        wait (rtr_io.cb.frame_n[7] !== 1'b0);
        @(rtr_io.cb iff(rtr_io.cb.frameo_n[7] === 1'b0));
      end
      begin: timer
        repeat(1000) @(rtr_io.cb);
        $display("Timed out!");
        $finish;
      end
    join_any
    
    disable fork;
  end join
  get_payload();
endtask

Process Handle

task recv();
  process thread_q[$];
  fork
    begin
      thread_q.push_back(process::self());
      wait (rtr_io.cb.frameeo_n[7] !== 1'b0);
      @(rtr_io.cb iff(rtr_io.cb.frameo_n[7] === 1'b0));
    end
    begin
      thread_q.push_back(process::self());
      repeat(1000) @(rtr_io.cb);
      $display("Timed out!");
      $finish;
    end
  join_any
  
  foreach (thread_q[i])
    if (thread_q[i].status != process::FINISHED)
      thread_q[i].kill();
  thread_q.delete();
endtask: recv
profile
Myongji UNIV. B.S. in Electronic Engineering

0개의 댓글