channel 2010

50
按按按按按按按按按按按 Communication Channels 按按按 , 按按按 按按按按 2010/12

Upload: -

Post on 06-May-2015

205 views

Category:

Technology


0 download

DESCRIPTION

SystemC Channel : SC_MUTEX, SC_FIFO, SC_SEMPHORE

TRANSCRIPT

Page 1: Channel 2010

按一下以編輯母片副標題樣式

Communication Channels

林敬倫 , 蘇文鈺

成大資訊

2010/12

Page 2: Channel 2010

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….

Page 3: Channel 2010

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

Page 4: Channel 2010

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

Page 5: Channel 2010

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.

Page 6: Channel 2010

sc_mutex syntax

• sc_mutex name_of_mutex– name_of_mutex.lock();//blocking

– name_of_mutex.trylock();//non-blocking

– name_of_mutex.unlock();

• 下圖是一個簡單的 bus based的範例,其中有兩個 masters 加上一個 slave 以及一個簡單的 bus arbiter

Page 7: Channel 2010

Mutex_bus

master0 master1

slave

Arbitration:Using sc_mutex

Page 8: Channel 2010

Main.cpp#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 master0("master0"); master1 master1("master1");

slave slave0("slave0"); bus bus0("bus0");

master0.clk(clk); master1.clk(clk);

master0.write_port(bus0); master1.write_port(bus0); bus0.write_port(slave0);

sc_start(50, SC_NS); cout << endl << endl; return 0;}

Page 9: Channel 2010

Master0.h#ifndef MASTER0_H#define MASTER0_H#include <systemc.h>#include "bus_if.h"

class master0 : public sc_module {public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1> write_port; void t1();SC_HAS_PROCESS(master0);

master0(sc_module_name name) { SC_THREAD(t1);

sensitive << clk.pos(); }};

void master0::t1(){

while(1){wait();

sc_time_stamp().print();printf("master0 request!\n");write_port->write(1,32);

wait(11,SC_NS);

sc_time_stamp().print();printf("master0 request!\n");write_port->write(5,53);

wait(11,SC_NS);}

}#endif // MASTER0_H

Page 10: Channel 2010

Master1.h#ifndef MASTER1_H#define MASTER1_H#include <systemc.h>#include "bus_if.h"

class master1 : public sc_module {public:

// clksc_in_clk clk;

// port declaration sc_port<bus_if,1> write_port;

void t1();

SC_HAS_PROCESS(master1);

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);

wait(10,SC_NS);

sc_time_stamp().print();printf("master1 request!\n");write_port->write(5,44);

wait(10,SC_NS);}

}#endif // MASTER1_H

Page 11: Channel 2010

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 declarationsc_port<bus_if,1> write_port;

// bus_if functionvoid write(unsigned addr, int

data);

// constructorbus(sc_module_name);

private:// sc_mutex declarationsc_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 functionpublic:

virtual void write(unsigned addr, int data) = 0;};

#endif // BUS_IF_H

Page 12: Channel 2010

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 unlockbus_mutex.lock();

write_port->write(addr,data);

// sc_mutex unlockbus_mutex.unlock();

}

Page 13: Channel 2010

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

Page 14: Channel 2010

result

Page 15: Channel 2010

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

Page 16: Channel 2010

09/12/9

Simple Bus Model

• 一樣是一個簡單的 Bus Model的範例 , 因為要求是可以有好幾個Modules同時進來 , 所以可以用 Semaphore來實現 .

Page 17: Channel 2010

09/12/9

Sem_bus

master0 master1

slave

Arbitration:Using sc_semaphore

Page 18: Channel 2010

Main.cpp#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 master0("master0"); master1 master1("master1");

slave slave0("slave0"); bus bus0("bus0");

master0.clk(clk); master1.clk(clk);

master0.write_port(bus0); master1.write_port(bus0); bus0.write_port(slave0);

sc_start(50, SC_NS); cout << endl << endl; return 0;}

Page 19: Channel 2010

Master0.h#ifndef MASTER0_H#define MASTER0_H#include <systemc.h>#include "bus_if.h"

class master0 : public sc_module { public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1> write_port; void t1();SC_HAS_PROCESS(master0);

master0(sc_module_name name) { SC_THREAD(t1);

sensitive << clk.pos(); }};

void master0::t1(){

while(1){wait();

sc_time_stamp().print();printf("master0 request!\n");write_port->write(1,32);

wait(11,SC_NS);

sc_time_stamp().print();printf("master0 request!\n");write_port->write(5,53);

wait(11,SC_NS);}

}#endif // MASTER0_H

Page 20: Channel 2010

Master1.h#ifndef MASTER1_H#define MASTER1_H#include <systemc.h>#include "bus_if.h"

class master1 : public sc_module {public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1>

write_port;

void t1();

SC_HAS_PROCESS(master1);

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);

wait(10,SC_NS);

sc_time_stamp().print();printf("master1 request!\n");write_port->write(5,44);

wait(10,SC_NS);}

}#endif // MASTER1_H

Page 21: Channel 2010

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 declarationsc_port<bus_if,1> write_port;

// bus_if functionvoid write(unsigned addr, int

data);

// constructorbus(sc_module_name);

private:// sc_semaphore declarationsc_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 functionpublic:

virtual void write(unsigned addr, int data) = 0;};

#endif // BUS_IF_H

Page 22: Channel 2010

Bus.cpp#include "bus.h"

// write_sem constructor assign count = 1bus::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();

}

Page 23: Channel 2010

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

Page 24: Channel 2010

result

Page 25: Channel 2010

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.

Page 26: Channel 2010

Bus Wrapper

• 接續上面的 Bus Model, 接到 Bus 的 Module有一個 Wrapper, Wrapper 上有一個 FIFO 來當 buffer, 這樣就可以運用 sc_fifo來當練習了 .

Page 27: Channel 2010

FIFO_bus

master0 master1

slave

Arbitration:Using wrapper(sc_fifo)

wrapper

Page 28: Channel 2010

Main.cpp#include <systemc.h>#include "master0.h"#include "master1.h"#include "wrapper.h"#include "slave.h"#include "bus.h"

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

master0 master0("master0");

master1 master1("master1");

wrapper wrapper0("wrapper0"); slave slave0("slave0"); bus bus0("bus0");

master0.clk(clk0);master1.clk(clk0);wrapper0.clk(clk0);

master0.write_port(wrapper0); master1.write_port(wrapper0);

wrapper0.write_port(bus0); bus0.write_port(slave0);

sc_start(50, SC_NS); cout << endl << endl; return 0;}

Page 29: Channel 2010

Master0.h#ifndef MASTER0_H#define MASTER0_H#include <systemc.h>#include "bus_if.h"

class master0 : public sc_module {public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1> write_port; void t1();SC_HAS_PROCESS(master0);

master0(sc_module_name name) { SC_THREAD(t1);

sensitive << clk.pos(); }};

void master0::t1(){

while(1){wait();

sc_time_stamp().print();printf("master0 request!\n");write_port->write(1,32);

wait(11,SC_NS);

sc_time_stamp().print();printf("master0 request!\n");write_port->write(5,53);

wait(11,SC_NS);}

}#endif // MASTER0_H

Page 30: Channel 2010

Master1.h#ifndef MASTER1_H#define MASTER1_H#include <systemc.h>#include "bus_if.h"

class master1 : public sc_module {public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1>

write_port;

void t1();

SC_HAS_PROCESS(master1);

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);

wait(10,SC_NS);

sc_time_stamp().print();printf("master1 request!\n");write_port->write(5,44);

wait(10,SC_NS);}

}#endif // MASTER1_H

Page 31: Channel 2010

Wrapper.h#ifndef WRAPPER_H#define WRAPPER_H#include <systemc.h>#include "bus_if.h"

class wrapper : public sc_module , public bus_if {public:

// clksc_in_clk clk;

// port declarationsc_port<bus_if,1> write_port;

void t1();void write(unsigned addr, int data);

SC_HAS_PROCESS(wrapper);

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;

unsigned addr_temp;int data_temp;

};

Page 32: Channel 2010

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

Page 33: Channel 2010

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 declarationsc_port<bus_if,1> write_port;

// bus_if functionvoid write(unsigned addr, int

data);

// constructorbus(sc_module_name);

#endif // BUS_H

#ifndef BUS_IF_H#define BUS_IF_H#include <systemc.h>

class bus_if : public sc_interface{

// pure virtual functionpublic:

virtual void write(unsigned addr, int data) = 0;};

#endif // BUS_IF_H

Page 34: Channel 2010

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);

}

Page 35: Channel 2010

09/12/9

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);

}#endif // SLAVE_H

Page 36: Channel 2010

09/12/9

result

Page 37: Channel 2010

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,

Page 38: Channel 2010

SystemC Simulation Kernel Work Flow

Page 39: Channel 2010

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.

Page 40: Channel 2010

09/12/9

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);………

Page 41: Channel 2010

SIGNAL_BUS

Page 42: Channel 2010

Bus說明

m0 m1

s0

arbitermultiplexerCLK

data

addr

data

addr

data

addr

enable_s

enable1

enable0

enable_mselect

used

Page 43: Channel 2010

Signal Bus File

main.cpp

master0.h

master1.h

slave.h

arbiter.h

multiplexer.h

Page 44: Channel 2010

main.cpp

Page 45: Channel 2010

master0.h

Page 46: Channel 2010

master1.h

Page 47: Channel 2010

slave.h

Page 48: Channel 2010

arbiter.h

Page 49: Channel 2010

multiplexer.h

Page 50: Channel 2010