verilog PLI 배우기(2); VPI handle

지난번에 이야기하고, 너무 많은 시간이 지났군요..
acc_, tf_ 와 다르게 VPI는 handle이라는 데이터 구조체를 이용하여 verilog simulator의 데이터 구조체에 접근합니다.

acc_, tf_ 의 경우에도 handle(정확히는 handle이라 부를만한 것)이 없는 건 아니지만, verilog simulator의 실제적인 데이터 object에 직접 접근한다는 개념이 강했습니다. 따라서, 필요한 object의 형태, 크기등의 여러가지 정보를 하나 하나 챙겨봐야 했지요.
하지만, VPI는 handle이라 불리는 복합적인 데이터 구조체를 이용하고, 이를 기반으로 편하게 verilog simulator의 데이터에 접근할 수 있습니다.

verilog VPI의 handle은 다음과 같이 선언하면 됩니다. (이를 위해서 vpi_user.h 가 include되어야 하는 건 당연하겠죠?)

vpiHandle  myhandle;

handle은 verilog simulator와 PLI루틴과의 관계를 정립할때 여러가지 형태를 가질 수 있도록 되어 있는데,  기본적으로 1-to-1 관계, 1-to-many관계, many-to-one의 관계로 나뉠수 있습니다.

각각은 말 그대로 verilog simulator의 객체를 PLI함수에서 볼때 어떻게 볼지에 대한 내용입니다. 이건 예제를 하나씩 보면서 배우면 되겠지요.

우선, verilog simulator에 접근해서 handle을 얻어와야 합니다.
이러한 동작은 vpi_handle(), vpi_iterate(), vpi_scan()과 같은 함수를 통하여 이루어집니다.
이 중에 vpi_handle()은 one-to-one관계를 만들어냅니다.

object_handle = vpi_handle(형태, 인자);

위의 함수는 형태와 대상 핸들명을 정하고 이에 맞는 핸들을 얻어오는 것입니다.
이때 형태를 vpiModule로 하면 verilog simulator의 모듈을 얻을 수 있겠고, callback 함수의 핸들을 얻으려면 vpiSysTfCall를 형태로 지정하면 되겠습니다.

vpiSysTfCall 의 경우 우리가 정의할 시스템 콜에 대하여 적용가능합니다.
즉, 우리가 시스템 콜을 정의하고, 이것을 verilog simulator에서 사용하는 경우에 이 형태가 vpiSysTfCall이 되는 것이겠죠. 따라서, 만일 우리가 verilog simulator에서 호출된 PLI함수에 어떤 전달 인자가 나왔는지 확인하려면 기본적으로 vpiSysTfCall이라는 형태의 handle을 받아야 합니다.

받아들인 핸들로부터 전달 인자(이것도 역시 핸들입니다.)를 추출하는 건 vpi_iterate() 함수를 사용합니다.
vpi_iterator는 여러개의 핸들을 몽창~ 추출하는 함수죠.(사실 핸들들을 몽창 이라기 보다, 여러 객체가 존재하는 하나의 핸들이라고 하는 것이 더 맞다고 생각합니다만…)

iterator는 C++, 특히 STL을 사용하시는 분들은 잘 아시겠지만, 반복자라 이야기하는 것은 여러 연속된 데이터를 순회하면서 데이터를 끄집어내는 형태의 데이터 구조를 뜻합니다. (뭐 예를 들어, linked list도 iterator요, array도 iterator죠.. 즉, 하나의 포인터로 순회하면서 여러개의 데이터에 접근 가능한 모든 데이터 형태를 일반화한 말..이라고 하면 좀 쉬울라나요? 더 어려울 라나요?)

자 간단하게 이 부분 까지의 코드를 만들어 볼까요?

 

vpiHandle  myhandle, arghandle;
// 시스템 콜 핸들을 얻어옵시다~
myhandle = vpi_handle(vpiSysTfCall, NULL);  
arg_handle = vpi_iterator(vpiArgument, myhandle);

이런식이죠.. 이제 다음에는 조금 더~ VPI의 모델에 대해서 알아보죠~

Verilog PLI 배우기 (1)

Verilog 사용자가 별로 없는지라(이 이야기에 발끈~하는 엔지니어 분들도 계시겠지만, 사실 C언어 사용자 보다는 적은거 맞잖습니까.., 우리나라 사람들중에 공학도 중에, 전자공학도 중에, verilog HDL을 쓰는 분을 따지면 별로 안되죠..^^) 국내에는 verilog PLI에 대하여 다루고 있는 페이지도 별로 없다.

개인적으로도 verilog PLI 관련 내용은 외국의 웹 페이지나, sutherland의 책을 참조하고 있는데, 국내의 많은 분들도 PLI를 적극적으로 이용하고 있음에 의심에 여지가 없건만 다들 숨기기만 하시니, 참조할 곳이 참 적기만 하다.

책이야기와 더불어 verilog PLI 이야기를 특히 VPI 이야기를 한번 해보려 한다.
뭐, 나도 PLI중의 tf_나 acc_는 좀 써봤지만, VPI는 얼마전에 처음 다루어 보았다.

그래서 공부 겸사 겸사.. 시간 될때 마다 정리해서 올려보려고한다.

우선 이번에는 PLI에 대한 대략적인 틀에 대해서~
(뭐 머리속에 있는 걸 쓰는 것이니 틀린것이 있을지도..)

PLI는 Programming Language Interface, 즉 verilog 에서 C/C++과 같은 언어와의 연동을 위하여 제공하는 일종의 API이다. 예전에 정의된 tf_, acc_(소위 PLI1.0)는 각각의 상황에 맞는 수많은 함수가 존재해서, 적절한 함수만 찾으면 쓰기는 쉽다는 장점이 있었다. (babyworm도 예전에 이걸 가지고 simulator와 verilog와 연동시킨 적이 있다..)

하지만, 함수가 너무 많아서 reference가 없으면 도저히 쓰기 어렵고, 명확히 정의되지 않았다는 단점이 있다(특히 verilog simulator와의 interfacing부분에 있어서 표준화 되어 있지 않다).

VPI는 다시 정의된 PLI함수로서 소위 PLI2.0으로 불린다. 예전에는 시뮬레이터 지원이 잘 안된다는 단점이 있었다지만, 요즘 시뮬레이터에서는 대부분 지원하고, 상당히 일관된 인터페이스를 지니고 있는 장점을 가지고 있다.

개인적으로는 acc_, tf_ 를 알면 verilog simulator가 어떻게 object들을 처리하는지 정말 잘~ 알게되는 장점(?)이 있는 반면, VPI는 그런 거 알 필요 없이 함수의 설정만 알아도 대부분 처리할 수 있다는 장점이 있다.
사용자 입장에서 어떤것이 편한 것인지는 말할 필요가 없다.

PLI는 기본적으로
1. 그 함수를  verilog simulator에 등록하는 부분을 지니고,
2. 해당 PLI 함수의 초기화, 호출, 크기 검사를 수행하는 callback 함수를 지니고 있다. (PLI1.0에는 misctf라는 재미나고 babyworm이 잘 사용하는 callback이 하나 더 있었다)

PLI를 verilog simlator와 연동하는 가장 쉬운 방법은 dynamic library로써 PLI함수를 컴파일하고, 이를 verilog simulator호출 시점에서 시뮬레이터에 알리는 것이다.

간단한 예를 들자면,

ncverilog +access+rwc +loadvpi=./aaaa.so:aaa_bootfunc test.v
이런식이다. 위에서 loadvpi라는 옵션을 사용헀는데, 이는 VPI 형태의 PLI함수를 포함한 동적 라이브러리를 시뮬레이션 시에 포함하되, aaa_bootfunc 이라는 것이 등록함수(다른 말로 bootstrap이라고 한다)로 사용할 것임을 알려주는 것이다.

다음번에는 실제적으로 VPI의 전반적인 얼계에 대해서 살펴봅시다.