Bài học SYSTEMC 12: Kênh trong SystemC: sc_mutex

Lu ROm

Administrator
Staff member
25 Tháng bảy 2014
481
119
43
31
One piece
vimach.net
- Trong SystemC có 2 loại kênh cơ bản là: kênh primitive(gốc) và kênh không primitive được gọi là kênh ‘hierarchical’ (phân cấp). Kênh primitive của SystemC được gọi là primitive vì chúng không chứa các hệ thống phân cấp, không có processes, và được thiết kế, sử dụng nhanh do sự đơn giản của nó. Tất cả các kênh primitive kế thừa từ lớp cơ sở sc_prim_channel. Bất kỳ kênh primitive có nguồn gốc từ: giao tiếp liên quan và lớp SystemC được định nghĩa trước: sc_prim_channel. Ngoài ra, một kênh primitive không được phép chứa các cấu trúc SystemC ví dụ như: threads, methods...
- Phần này mình sẽ giới thiệu các kênh primitive cơ bản nhất trong SystemC đó là: sc_mutex, sc_semaphore, và sc_fifo. Những kênh này được sử dụng riêng lẻ hoặc có thể được kết hợp như một phần của "non-primitive'. Một số kênh primitive nâng cao mình sẽ giới thiệu sau. Các kênh này có thể được khai báo như sau:
Mã:
// A 32×16 bits elements fifo
sc_fifo<sc_lv<16> > inputFifo(32);
// A 16 bits bus
sc_signal<sc_lv<16> > dataBus;
// A 4 tokens semaphore
sc_semaphore gateKeeper(4);
1. sc_mutex
- Mutex là kênh primitive dành cho đối tượng loại trừ lẫn nhau, kiểm soát quyền truy cập vào tài nguyên được chia sẻ của tiến trình đồng thời.. Trong chương trình, một mutex là một đối tượng chương trình cho phép nhiều luồng chương trình chia sẻ nguồn tài nguyên chung, chẳng hạn như truy cập tập tin mà không xung đột.
- Trong suốt quá trình soạn thảo, một mutex được tạo ra với một tên duy nhất; Sau đó, bất kỳ processes cần tài nguyên phải khóa mutex để ngăn chặn các processes khác sử dụng các tài nguyên được chia sẻ. Processes này cần mở khóa mutex khi tài nguyên không dùng đén nữa. Nếu một processes cố gắng truy cập một mutex đã bị khóa, processes đó được ngăn chặn cho đến khi mutex đã sẵn sàng (hay mở khóa).
- SystemC cung cấp mutex qua các kênh sc_mutex. Lớp này chứa một số methods bao gồm cả các kiểu blocked và unblocked. Hãy nhớ rằng methods blocking chỉ có thể được sử dụng trong processes SC_THREAD.
** Ví dụ một số loại mutex:
Mã:
sc_mutex NAME;
// To lock the mutex NAME (wait until
// unlocked if in use)
NAME. lock();
// Non-blocking, returns true if success, else false
N A M E. trylock()
// To free a previously locked mutex
NAME. unlock();
** Mình để tiếng anh dễ hiểu hơn là dịch :D.
**** Ví dụ sau về các người quản lý trạm xăng là một ví dụ tốt về một nguồn tài nguyên được chia sẻ. Chỉ có một chiếc xe tại một thời điểm được nạp đầy, giả sử chỉ có một máy bơm gas duy nhất.
Một ví dụ khác của một tài nguyên cần một mutex là điều khiển của một chiếc ô tô. Chỉ có một người điều khiển tại một thời điểm và có thể ngồi ở chỗ ngồi điều khiển. Trong mô phỏng modeling có sự ảnh hưởng của người điều khiển trên phố với một loạt các xe khác.
Mã:
sc_mutex drivers_seat;
car->drivers_seat. lock(); // sim driver acquiring
// driver's seat
car->start();
// operate vehicle
car->stop();
car->drivers_seat. unlock(); // sim driver leaving
// vehicle
- Một nhược điểm của sc_mutex là thiếu một sự kiện báo hiệu khi một sc_mutex được giải phóng, điều này đòi hỏi phải dùng nhiều lần trylock dựa trên một số sự kiện hoặc thời gian delay khác. Hãy nhớ rằng, trừ khi process của bạn wait (thông qua wait or return), bạn sẽ không cho phép process khi đang sở hữu nguồn tài nguyên và giải phóng nguồn tài nguyên đó, nếu không mô phỏng sẽ treo.
*** Code hoàn chỉnh trong một chương trình SystemC.
Mã:
#include <systemc.h>

SC_MODULE (sc_mutex_example) {
  sc_in<bool> clock;

  sc_mutex   bus;
  int     cnt;


  void do_bus(int who) {
    cout << "@" << sc_time_stamp() <<" Bus access by instance " << who << endl;
  }

  void do_test1() {
    while (true) {
      wait();
      cout << "@" << sc_time_stamp() <<" Checking mutex intance 0"<<endl;
      // Check if mutex is available
      if (bus.trylock() != -1) {
        cout << "@" << sc_time_stamp() <<" Got mutex for intance 0"<<endl;
        cnt ++;
        do_bus(0);
        wait(2);
        // Unlock the mutex
        bus.unlock();
      }
      if (cnt >= 3) {
        sc_stop(); // sc_stop triggers end of simulation
      }
    }
  }

  void do_test2() {
    while (true) {
      wait();
      cout << "@" << sc_time_stamp() <<" Checking mutex intance 1"<<endl;
      // Wait till mutex is available
      bus.lock();
      cout << "@" << sc_time_stamp() <<" Got mutex for intance 1"<<endl;
      do_bus(1);
      wait(3);
      // Unlock the mutex
      bus.unlock();
    }
  }

  SC_CTOR(sc_mutex_example) {
    cnt = 0;
    SC_CTHREAD(do_test1,clock.pos());
    SC_CTHREAD(do_test2,clock.pos());
  }
};

int sc_main (int argc, char* argv[]) {
  sc_clock clock ("my_clock",1,0.5);

  sc_mutex_example  object("wait");
    object.clock (clock.signal());

  sc_start(0); // First time called will init schedular
  sc_start();  // Run the simulation till sc_stop is encountered
  return 0;// Terminate simulation
}
** Kết quả mô phỏng:
upload_2016-8-5_11-1-40.png