본문 바로가기

SystemC Tutorial

Ch3. SystemC의 구성 요소 - Primitive Channel

반응형

 

앞서도 얘기 했지만 primitive channel에는 대표적으로 sc_signal과 sc_fifo가 있다. 그 외 여러가지가 있지만 자세한 것은 spec을 참조 하도록 하고 여기서는 가장 사용 빈도가 높은 sc_signal과 sc_fifo에 대해서만 알아 보자.

1. sc_signal<T>

이 channel에는 sc_signal_inout_if<T>의 read/write method 함수가 구현 되어 있다. 즉 sc_signal은 verilog HDL의 wire와 같은 개념으로써 module과 module간의 통신 매개체가 되는 것이다.

channel을 사용할 때 공통적으로 주의해야 할 사항이 있다. 그것은 동시성을 위한 메카니즘인데 channel의 read/write method를 통해 어떤 값을 읽고 쓸 경우 그 결과는 시뮬레이션 단위 지연 시간 만큼 후에 반영이 된다는 것이다.

예를 들어 보자. 아래 a라는 sc_signal에 초기 값이 0이라고 가정하자.

 sc_signal<int> a;

 int y;

 a.write(10);

 y = a.read();

    

자 y에는 어떤 값이 있을까? 답은 0이다. 그럼 언제 10이라는 값이 써지는 것일 까? 아래 예제를 보자.

a.write(10);

wait();

y = a.read();

이제 y를 출력하면 10이 들어가 있다. 즉 SystemC simulation kernel이 현재 시간에 pending 되어 있는 모든 event처리 (여기서는 a.write(10);)을 진행하고 다음 event로 simulation time을 증가 시켜야 (여기서는 wait();) 결과 값이 반영되는 것이다.

2. sc_fifo<T>

sc_fifo에는 blocking read/write method와 non-blocking read/write method 그리고 몇 가지 FIFO 상태를 알 수 있는 method가 구현 되어 있다.

보통 functional modeling이나 transaction level modeling에서는 block read/write method를 사용하고 실제 RTL level의 HW구현에는 non-blocking method를 사용한다.

block method는 read()/write()이고 non-blocking method는 nb_read()/nb_write()이다.

read()를 call하면 fifo에 데이터가 있으면 return하고 데이터가 없으면 데이터가 들어올 때 까지 return하지 않는다. nb_read()를 call하면 데이터가 있으면 데이터를 읽고 true를 return하고 데이터가 없으면 false를 return한다. write()를 call하면 fifo에 빈영역이 있으면 바로 write하고 빈 영역이 없으면 빈 영역이 생길 때 까지 기다렸다 write하고 return 한다. nb_write()를 call 하면 빈 영역이 있으면 바로 write하고 true를 return하고 빈 영역이 없으면 false를 return한다.

이 외에 num_available()이란 method가 있는데 이것은 읽을 수 있는 데이터 갯수를 리턴한다.

num_free() 는 쓰기 가능한 빈 영역 갯수를 리턴한다.

sc_fifo를 이용한 예제는 아래와 같다

#include <stdio.h>
#include <systemc.h>


class Adder : public sc_module
{
	public :

 	sc_in_clk	  clk;
    sc_in<int>    a;
    sc_in<int>    b;
    sc_fifo_out<int>   y;
 
    SC_HAS_PROCESS(Adder);
 
    Adder(sc_module_name name) : sc_module(name) {
        SC_THREAD (main);
        sensitive << clk.pos();
    }

	void main();
};
 
void Adder::main()
{
    while(1)
    {
        y.write(a+b); 
        wait();
    }
}

int sc_main(int argc, char *argv[])
{
	sc_signal<int> a;
	sc_signal<int> b;
	sc_fifo<int> y_fifo(10);

	sc_clock clk("clock", 10, SC_NS, 0.5, 0.0, SC_NS);

	Adder u_Adder("adder");

	u_Adder.clk(clk);
	u_Adder.a(a);
	u_Adder.b(b);
	u_Adder.y(y_fifo);

	a = 10;
	b = 20;
	sc_start(100, SC_NS);

	printf("%d + %d = %d\n", a.read(), b.read(), y_fifo.read());

	return 0;

}
반응형