Channel 2010

471 views

Published on

SystemC Channel : SC_MUTEX, SC_FIFO, SC_SEMPHORE

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
471
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Channel 2010

  1. 1. Communication Channels 按一下以編輯母片副標題樣式 林敬倫 , 蘇文鈺 成大資訊 2010/12
  2. 2. Without Channels • One can still exchange data among modules. • Problems: – Data access may not be well scheduled. – It is possible that multiple processes try to access but clear order is not set up. – Events can be used to set up the order but it is likely that events may be missed. – No handshaking mechanism is embedded. – It does not map to HW architecture. – And so on….
  3. 3. Using channels • • • • For all communication issues, it is recommended to solve the above problems using channels. Channel is a SystemC embedded mechanism. Can be used to map to real HW architecture and communication protocols. Two basic types of channels are provided: – Primitive – Hierarchical
  4. 4. Primitive Channels • For “primitive” type, no process, hierarchy, and so on in order to make the channels fast. • Inherit from the base class, sc_prim_channel. • Three simple SystemC channels: – sc_mutex – sc_semaphore – sc_fifo
  5. 5. sc_mutex • • • • • Mutex is a program object allowing multiple threads to share a common resource without colliding. During elaboration, a mutex is created. Then, any process wants to use the resource must lock the mutex to prevent others from accessing the same source. After its access, the process must unlock the mutex to let others access the resource. When a process try to access a locked mutex, it is prevented until the mutex is unlocked. In SystemC, both blocking and unblocking types are supported. No signal is available to indicate that a mutex is available. SO, using trylock may be a method but it may slow down the simulation.
  6. 6. sc_mutex syntax • sc_mutex name_of_mutex – – name_of_mutex.trylock();//non-blocking – • name_of_mutex.lock();//blocking name_of_mutex.unlock(); 下圖是一個簡單的 bus based 的範例,其中 有兩個 masters 加上一個 slave 以及一個簡 單的 bus arbiter
  7. 7. Mutex_bus Arbitration: Using sc_mutex master0 master1 slave
  8. 8. Main.cpp slave slave0("slave0"); bus bus0("bus0"); #include <systemc.h> #include "master0.h" #include "master1.h" #include "slave.h" #include "bus.h" int sc_main (int argc , char *argv[]) { sc_clock clk("clk0", 1 , SC_NS , 0.5); master0.clk(clk); master1.clk(clk); master0.write_port(bus0); master1.write_port(bus0); bus0.write_port(slave0); master0 master0("master0"); master1 master1("master1"); sc_start(50, SC_NS); cout << endl << endl; return 0; }
  9. 9. Master0.h #ifndef MASTER0_H #define MASTER0_H #include <systemc.h> #include "bus_if.h" class master0 : public sc_module { public: // clk sc_in_clk clk; void master0::t1() { while(1){ wait(); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(1,32); // port declaration sc_port<bus_if,1> write_port; void t1(); SC_HAS_PROCESS(master0); master0(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } }; wait(11,SC_NS); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(5,53); wait(11,SC_NS); } } #endif // MASTER0_H
  10. 10. Master1.h #ifndef MASTER1_H #define MASTER1_H #include <systemc.h> #include "bus_if.h" class master1 : public sc_module { public: // clk sc_in_clk clk; }; master1(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } void master1::t1() { while(1){ wait(); // port declaration sc_port<bus_if,1> write_port; sc_time_stamp().print(); printf("master1 request!n"); write_port->write(3,60); void t1(); wait(10,SC_NS); SC_HAS_PROCESS(master1); sc_time_stamp().print(); printf("master1 request!n"); write_port->write(5,44); } wait(10,SC_NS); } #endif // MASTER1_H
  11. 11. Bus.h & Bus_if.h #ifndef BUS_H #define BUS_H #include <systemc.h> #include "bus_if.h" class bus :public bus_if, public sc_module { public: // port declaration sc_port<bus_if,1> write_port; data); // bus_if function void write(unsigned addr, int // constructor bus(sc_module_name); private: // sc_mutex declaration sc_mutex bus_mutex; }; #endif // BUS_H #ifndef BUS_IF_H #define BUS_IF_H #include <systemc.h> class bus_if : public sc_interface { // pure virtual function public: virtual void write(unsigned addr, int data) = 0; }; #endif // BUS_IF_H
  12. 12. Bus.cpp #include "bus.h" bus::bus(sc_module_name nm) : sc_module(nm) { } void bus::write(unsigned addr, int data) { // sc_mutex lock process, wait for unlock bus_mutex.lock(); write_port->write(addr,data); } // sc_mutex unlock bus_mutex.unlock();
  13. 13. Slave.h #ifndef SLAVE_H #define SLAVE_H #include <systemc.h> #include "bus_if.h" class slave : public sc_module , public bus_if { public: void write(unsigned addr, int data); slave(sc_module_name name) { for(int a = 0 ; a<32 ; a++) { memory[a] = 0; } } private: int memory[32]; }; void slave::write(unsigned addr, int data) { memory[addr] = data; wait(2, SC_NS); sc_time_stamp().print(); printf(" slave get data %d at addr %d !n",data,addr); } #endif // SLAVE_H
  14. 14. result
  15. 15. sc_semaphore • To have more than one resources to choose from, one can use semaphore. • Mutex here is one special case of semaphore. • When a process finishes with a resource, it must post a notice. • Syntax: sc_semaphore name_or_semaphore(count) – name_of_semaphore.wait(); //blocking – name_of_semaphore.trywait(); //non-blocking – name_of_semaphore.get_value();// return # of free semaphores – name_of_semaphore.post(); //when free a resource
  16. 16. Simple Bus Model • 一樣是一個簡單的 Bus Model 的範例 , 因為 要求是可以有好幾個 Modules 同時進來 , 所以可以用 Semaphore 來實現 . 09/12/9
  17. 17. Sem_bus Arbitration: Using sc_semaphore master0 master1 slave 09/12/9
  18. 18. Main.cpp slave slave0("slave0"); bus bus0("bus0"); #include <systemc.h> #include "master0.h" #include "master1.h" #include "slave.h" #include "bus.h" master0.clk(clk); master1.clk(clk); master0.write_port(bus0); master1.write_port(bus0); bus0.write_port(slave0); int sc_main (int argc , char *argv[]) { sc_clock clk("clk0", 1 , SC_NS , 0.5); sc_start(50, SC_NS); cout << endl << endl; return 0; master0 master0("master0"); master1 master1("master1"); }
  19. 19. #ifndef MASTER0_H #define MASTER0_H #include <systemc.h> #include "bus_if.h" Master0.h class master0 : public sc_module { public: // clk sc_in_clk clk; void master0::t1() { while(1){ wait(); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(1,32); // port declaration sc_port<bus_if,1> write_port; void t1(); SC_HAS_PROCESS(master0); master0(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } }; wait(11,SC_NS); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(5,53); wait(11,SC_NS); } } #endif // MASTER0_H
  20. 20. Master1.h #ifndef MASTER1_H #define MASTER1_H #include <systemc.h> #include "bus_if.h" class master1 : public sc_module { public: // clk sc_in_clk clk; }; master1(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } void master1::t1() { while(1){ wait(); sc_time_stamp().print(); printf("master1 request!n"); write_port->write(3,60); // port declaration sc_port<bus_if,1> write_port; wait(10,SC_NS); void t1(); sc_time_stamp().print(); printf("master1 request!n"); write_port->write(5,44); SC_HAS_PROCESS(master1); } wait(10,SC_NS); } #endif // MASTER1_H
  21. 21. Bus.h & Bus_if.h #ifndef BUS_H #define BUS_H #include <systemc.h> #include "bus_if.h" class bus :public bus_if, public sc_module { public: // port declaration sc_port<bus_if,1> write_port; data); // bus_if function void write(unsigned addr, int // constructor bus(sc_module_name); private: // sc_semaphore declaration sc_semaphore write_sem; }; #endif // BUS_H #ifndef BUS_IF_H #define BUS_IF_H #include <systemc.h> class bus_if : public sc_interface { // pure virtual function public: virtual void write(unsigned addr, int data) = 0; }; #endif // BUS_IF_H
  22. 22. Bus.cpp #include "bus.h" // write_sem constructor assign count = 1 bus::bus(sc_module_name nm) : sc_module(nm), write_sem(1) { } void bus::write(unsigned addr, int data) { // sc_semaphore.wait, count-- (1=>0) write_sem.wait(); write_port->write(addr,data); } // sc_semaphore.post, count++ (0=>1) write_sem.post();
  23. 23. Slave.h #ifndef SLAVE_H #define SLAVE_H #include <systemc.h> #include "bus_if.h" class slave : public sc_module , public bus_if { public: void write(unsigned addr, int data); slave(sc_module_name name) { for(int a = 0 ; a<32 ; a++) { memory[a] = 0; } } private: int memory[32]; }; void slave::write(unsigned addr, int data) { memory[addr] = data; wait(2, SC_NS); sc_time_stamp().print(); printf(" slave get data %d at addr %d !n",data,addr); } #endif // SLAVE_H
  24. 24. result
  25. 25. SC_FIFO • Good for architecture modeling • Suitable for data flow modeling too. • Simple to implement. • Default sc_fifo depth is 16, with its data type specified. • The data type of sc_fifo can be complex structure. • It can be used to buffer data between two processing units, data packets in communication networks, and so on.
  26. 26. Bus Wrapper • 接續上面的 Bus Model, 接到 Bus 的 Module 有一個 Wrapper, Wrapper 上有一個 FIFO 來 當 buffer, 這樣就可以運用 sc_fifo 來當練習 了.
  27. 27. FIFO_bus Arbitration: Using wrapper(sc_fifo) master0 master1 wrapper slave
  28. 28. Main.cpp #include <systemc.h> #include "master0.h" #include "master1.h" #include "wrapper.h" #include "slave.h" #include "bus.h" wrapper wrapper0("wrapper0"); slave slave0("slave0"); bus bus0("bus0"); int sc_main (int argc , char *argv[]) { sc_clock clk0("clk0", 1 , SC_NS , 0.5); master0.write_port(wrapper0); master1.write_port(wrapper0); wrapper0.write_port(bus0); bus0.write_port(slave0); master0 master0("master0"); master1 master1("master1"); sc_start(50, SC_NS); cout << endl << endl; return 0; master0.clk(clk0); master1.clk(clk0); wrapper0.clk(clk0); }
  29. 29. #ifndef MASTER0_H #define MASTER0_H #include <systemc.h> #include "bus_if.h" Master0.h class master0 : public sc_module { public: // clk sc_in_clk clk; void master0::t1() { while(1){ wait(); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(1,32); // port declaration sc_port<bus_if,1> write_port; void t1(); SC_HAS_PROCESS(master0); master0(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } }; wait(11,SC_NS); sc_time_stamp().print(); printf("master0 request!n"); write_port->write(5,53); wait(11,SC_NS); } } #endif // MASTER0_H
  30. 30. Master1.h #ifndef MASTER1_H #define MASTER1_H #include <systemc.h> #include "bus_if.h" class master1 : public sc_module { public: // clk sc_in_clk clk; master1(sc_module_name name) { SC_THREAD(t1); sensitive << clk.pos(); } }; void master1::t1() { while(1){ wait(); sc_time_stamp().print(); printf("master1 request!n"); write_port->write(3,60); // port declaration sc_port<bus_if,1> write_port; wait(10,SC_NS); void t1(); sc_time_stamp().print(); printf("master1 request!n"); write_port->write(5,44); SC_HAS_PROCESS(master1); wait(10,SC_NS); } } #endif // MASTER1_H
  31. 31. Wrapper.h SC_HAS_PROCESS(wrapper); #ifndef WRAPPER_H #define WRAPPER_H #include <systemc.h> #include "bus_if.h" class wrapper : public sc_module , public bus_if { public: // clk sc_in_clk clk; // port declaration sc_port<bus_if,1> wrapper(sc_module_name name) { sc_fifo<unsigned> addr_fifo(10); sc_fifo<int> data_fifo(10); SC_THREAD(t1); sensitive << clk.pos(); } private: sc_fifo<unsigned> addr_fifo; sc_fifo<int> data_fifo; write_port; void t1(); void write(unsigned addr, int data); }; unsigned addr_temp; int data_temp;
  32. 32. Wrapper.h(cont’) void wrapper::t1() { while(1) { } } wait(); sc_time_stamp().print(); printf(" wrapper request!n"); addr_temp = addr_fifo.read(); data_temp = data_fifo.read(); write_port->write(addr_temp,data_temp); sc_time_stamp().print(); printf(" wrapper write %d in %d n",data_temp,addr_temp); void wrapper::write(unsigned addr, int data) { sc_time_stamp().print(); printf(" fifo.write data = %d ; addr = %d n",data,addr); addr_fifo.write(addr); data_fifo.write(data); } #endif // WRAPPER_H
  33. 33. Bus.h & Bus_if.h #ifndef BUS_H #define BUS_H #include <systemc.h> #include "bus_if.h" #ifndef BUS_IF_H #define BUS_IF_H #include <systemc.h> class bus :public bus_if, public sc_module { public: // port declaration sc_port<bus_if,1> write_port; class bus_if : public sc_interface { // pure virtual function public: virtual void write(unsigned addr, int data) = 0; }; data); // bus_if function void write(unsigned addr, int // constructor bus(sc_module_name); #endif // BUS_H #endif // BUS_IF_H
  34. 34. Bus.cpp #include "bus.h" bus::bus(sc_module_name nm) : sc_module(nm), write_sem(1) { } void bus::write(unsigned addr, int data) { write_port->write(addr,data); }
  35. 35. Slave.h #ifndef SLAVE_H #define SLAVE_H private: int memory[32]; }; #include <systemc.h> #include "bus_if.h" class slave : public sc_module , public bus_if { public: void write(unsigned addr, int data); 09/12/9 void slave::write(unsigned addr, int data) { memory[addr] = data; wait(2, SC_NS); } #endif // SLAVE_H
  36. 36. result 09/12/9
  37. 37. The use of Signals • • • • When modeling signal on something like electronic wire, When concurrent executions of modules are required and execution orders of modules are important, When using wait() and notify() cosumes too much time, When using FIFO consuming too much resources,
  38. 38. SystemC Simulation Kernel Work Flow
  39. 39. Signal Channel • Signal channels use the update phase as a point of synchronization. • Each such channel has to store the current value and the new value. • • • • The incoming value is stored into the new position instead of the current position. When in update phase (Kernel calls update_request()), the current value is updated with the new value. Therefore, contention is resolved. All these are done within a delta cycle. If one writes to a channel and reads the channel within the same delta cycle, one will find the result is not the value just been written.
  40. 40. sc_signal • • • When using write(), the evaluate-update is performed, too. That is, it calls sc_prim_channle:: request_update() and sc_signal::update(). sc_signal behaves like VHDL’ signal and Verilog’s reg. By the way. Only one process can write to a sc_signal in order to avoid race condition. sc_signal <datatype> name_of_signal; name_of_signal.write(new_value); name_of_signal.read(name_of_var); sensitive << name_of_signal.default_event(); wait(name_of_signal.default_event); ……… 09/12/9
  41. 41. SIGNAL_BUS
  42. 42. Bus 說明 m0 m1 enable1 addr addr data data enable0 CLK enable_m select multiplexer addr used data s0 enable_s arbiter
  43. 43. Signal Bus File main.cpp master0.h master1.h slave.h arbiter.h multiplexer.h
  44. 44. main.cpp
  45. 45. master0.h
  46. 46. master1.h
  47. 47. slave.h
  48. 48. arbiter.h
  49. 49. multiplexer.h

×