본문 바로가기

SystemC Tutorial

Ch1. SystemC의 구성요소 - module

반응형

SystemC는 hardware를 표현하고 시뮬레이션 하기 위한 class library라고 할 수 있다. 그러면 어떤 class들이 있을까? 그 중 대표적인 것이 sc_module이다.

Verilog에서 hardware를 기술할 때 module이라고 하는 keyword를 사용하여 hardware module을 기술한다. Hardware module은 input, output port와 내부에 function을 기술하기 위한 always문과 같은 process들이 존재한다. process라고 하는 것은 sensitivity list에 감응하여 동작하는 단위 기능이라고 생각하면 좋을 것이다. 주지 하다 싶이 process들은 서로 concurrent하게 동작하여 hardware특성을 기술할 수 있는 것이다.

마찬가지로 SystemC에서도 Verilog의 module과 같은 개념으로 sc_module이 존재한다. 이것은 일반적인 sw에서의 class이지만 hardware적인 특성을 반영하기 위하여 몇 가지 특징을 같고 있다. sc_module class에서 input/output port를 기술할 수 있고 sensitivity list에 감응하여 동작하는 process를 정의할 수 있다. 백문이 불여일견이라고 예제 하나를 살펴 보자.

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

class Adder : public sc_module
{
	public :

    sc_in<int>    a;
    sc_in<int>    b;
    sc_out<int>   y;
 
    SC_HAS_PROCESS(Adder);
 
    Adder(sc_module_name name) : sc_module(name) {
        SC_THREAD (main);
        sensitive << a << b;
    }

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

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

	Adder u_Adder("adder");

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

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

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

	return 0;

}

위의 예제는 a와 b를 입력으로 받아 더해서 y로 출력하는 가산기 이다.

Adder라는 class는 sc_module에서 파생되는 것을 알 수 있다. Hardware 관점에서 본다면 Adder라고 하는 module을 만든다고 보면 된다. C++의 class선언이므로 그 안에는 각 종 변수와 멤버 펑션들이 들어가게 될 것이다.  여기서 sc_in<int> a;와 같은 것은 hardware에서 input port 선언과 동일한 효과를 내는 것으로 sc_in 이라고 하는 class 변수라고 생각하면 된다. '<>'안에 들어간 type의 parameter를 갖는 class인 것으로 template class라고 한다.

sc_out은 output port를 구현 하기 위한 class이다. port class에 대해서는 다음에 자세히 설명하기로 한다. 다시 정리하면 hardware 의 input/output port는 SystemC의 sc_in/sc_out class 변수로 정의할 수 있다.

SC_HAS_PROCESS(Adder);는 이 class 의 constructor를 구현하기 위한 macro이다. C++의 class에는 constructor와 deconstructor가 있는데 SystemC에서는 이를 hardware 개념에 맞게 단순화 할 수 있도록 macro를 제공한다. SC_CTOR이 그것인데 이를 사용할 경우 user 변수등을 초기화 하는데 제한이 생기게 되어 SC_HAS_PROCESS() macro를 사용한다. 좀 어렵다면 module을 선언하기 위해 필수적으로 들어간다고 생각하고 인자로 class name을 사용한다는 것 정도만 기억하자.

Adder(sc_module_name name) : sc_module(name) {}는 Adder class의 constructor(생성자)이다. 일반적인 class의 생성자와 동일한 모양이고 중요한 것은 괄호안의 sc_module_name name을 parameter로 전달하는 것이다.  SystemC에서는 hardware의 계층구조를 sc_module_name을 통해 수립한다. 즉 Adder class의 상위 class인 sc_module에 Adder의 sc_module_name class를 전달하는 것이다.

생성자 안에는 SC_THREAD(main);이 있는데 이것은 main이라고 하는 thread를 등록하는 것이다. SW에서 thread는 병렬로 수행되는 최소의 process 단위이다.  어쨌든 hardware의 동시성을 구현하기 위해 thread만큼 적합한 것은 없을 것이다. Verilog에서 보면 always 구문과 같은 것으로 생각하면 이해가 쉬울 것이다.

sensitive << a << b;은 main이라고 하는 thread가 언제 SystemC kernel에 의해 수행 되느냐 하는 것인데, 즉 a 또는 b의 값이 변경 될 때 마다 수행된다는 것이다. Verilog에서 @()에 드러가는 sensitivity list와 동일한 것이다.

main thread를 살펴 보면 while(1)의 무한 루프가 있는 것이 좀 의아할 수도 있다. 하지만 Verilog를 사용해 본 사람이라면 이해가 쉬울 것이다. 즉 always@()문은 sensitivity list의 값이 변화하면 수행하고 그 것을 무한히 반복하는 것이다. main thread의 wait()문은 SystemC kernel scheduler에게 수행 제어권을 넘겨주는 것이다. 이런 것을 선점형 OS라고 하던가? 즉 main thread가 수행되면 wait()가 올 때까지 다른 어떤 thread도 수행 할 수 없는 것이다. 따라서 SystemC의 모든 thread는 자기 할 일 하고 wait()를 call하여 제어권을 kernel에게 넘겨 주어야 한다.

반응형