Category Archives: SoC & IP design

PLI와 Simulator의 연결(I)

Automated Functional Verification 방법에는 여러 가지가 있지만, testvector 발생 유닛(보통 Directed Random방식을 사용하지요?)과 golden model을 이용한 checker model을 만들어서 DUV(Design Under Verification)의 결과와 비교하는 것이 가장 편한 방법 중에 하나임은 부정할 수 없습니다. (여담입니다만, 국내에서는 많은 경우 golden model없이 설계하는 경우가 많아서 검증을 위하여 작성한 golden model이 실제로 RTL보다도 정확성이 떨어지는 경우가 있다는 것이 문제가 종종 발생합니다. 여기서는 golden모델의 확보에 대한 이야기는 나중으로 미루죠.)보통 golden model은 C model을 이용하게 되는데, C 모델을 Verilog와 동시에 simulation하는 것은 그리 녹녹한 일이 아닙니다.


저는 프로세서를 대부분 다루기 때문에 C모델이라 함이 대부분 ISS simulator가 됩니다. 이후에 Simulator와 C모델은 그냥 섞어 쓸 가능성이 높은데, 보시는 분께서 편하신 대로 생각하시면 되겠습니다.


우선 Simulator를 만들 때 그 목적을 정확히 할 필요가 있습니다. 초기에 Simulator의 목적은 executable spec.의 의미가 가장 중요한 의미였을 것입니다. 그래서, 대부분 function level의 정확성을 가지지요. 프로세서의 경우 보통 이야기하는 ISS(Instruction Set Simulator)정도의 수준일 것입니다.


이때 고려하는 사항은 동작의 정확성, 빠른 동작 속도, 유연한 변경 가능성(design space exploration을 해야 하니까요)과 같은 것을 고려하게 됩니다.


그런데, 아시다시피 Verilog와 Simulation을 한다던지, Verilog Model대신 사용하려고 할 경우에는 ISS level뿐만 아니라, BFM 수준, 간혹은 Pin-level accuracy를 필요하게 됩니다. 통신이나 영상쪽의 모델은 뭐 Functional model이나 BFM이나 큰 어려움이 없습니다. Latency가 거의 정의되어 있기 때문이지요.


프로세서의 경우 약간 복잡해지는데, hazard의 발생, instruction issue rate의 변화, exception의 발생을 고려해야 하는데, 이 경우 bus function이 발생하는 Instruction Fetch와 Data Access stage의 동작을 모사하기 위해서는 대부분의 pipeline을 표현해내야 합니다. 예전에 pipeline 수준의 accuracy를 가지는 simulator를 만들고, pin-level interface를 붙여서 나름대로 쓸만한 PLI model을 만든 적이 있지요. 단지 문제는 pipeline수준의 accuracy를 가지다 보니, 너무 너무 느려져 버린거지요.


쉽게 쉽게 만들려면 functional model로 simulator를 만들고, Verilog Model(DUV)상에 하나의 명령이 retire되는 순간에 register들의 값을 비교하는 방법도 가능합니다. 하지만, 해당 model이 불필요한 hazard 발생은 없는지, Instruction Fetching에 불필요한 사항이 추가되지는 않았는지 확인 할 수는 없습니다. (당연하죠.. reference model이 functional model이니 timing spec.을 만족시켰는지는 알수 없는것이지요)


흠.. 많이 옆으로 샜는데요..


C Model과 Verilog와 붙이는 방법이 Verilog-PLI (Programming Language Interface)를 이용하는 겁니다. Simulator는 clock단위로 동작하므로, 느낌상 아래와 같이 동작시키면 될 것 같습니다. 이런 경우에 verilog에서 C function을 호출할 때 가장 많이 사용되는 건 calltf()를 이용하는 방법입니다.



always @(posedge clk or negedge rst_x) begin


  $run_sim_calltf(xxxx);


end


즉, run_sim()을 calltf()의 callback function으로 등록하는 겁니다. 그리고, 매 클럭 calltf()를 불러주는 것이지요.


근데, simualtor의 이전 상태를 계속적으로 보존해야 하는 경우에는 매 클럭 새롭게 호출되는 calltf()를 이용할 때 문제가 있을 수 있습니다. (사실 그리 어려운 일은 아닙니다만, 예를 들기 위하여 ^^ ) 그래서, 내용을 보존하고 싶을 때는 misctf()를 사용하는 것도 괜찮습니다. misctf()는 원래 verilog simulation의 이런 저런 정리 작업을 하는데 사용하는 목적으로 만드는 건데요. 아래와 같이도 사용할 수 있습니다.



initial begin


  $run_sim_misctf(data, reason, paramvc);


end


뭐 이런 느낌입니다. misctf()의 경우 시뮬레이터의 초기 시에 simulator에 연결된 이후에 simulator의 종료 시까지 계속 머무르면서 파라미터의 값이 변경 될 때 마다 제어권을 가집니다. 이 파라미터의 변화시마다 클럭이 변화되었는지 확인하고, 클럭이 변화하였을 때 값을 호출하면 되겠습니다.


아래는 한 4년 전에 만든 PLI 모델중의 misctf부분인데요.. 실제 구현은 없으니 공개해도 별 문제 없을 것입니다. ^^; 대략 이런 느낌으로 만드시면 됩니다. 🙂
다음 번에는 좀 더 재미난 PLI 함수를 다루어보죠.. (아.. VPI는 초반에 좀 다루지 않네요. ^^; Blog의 예제를 위해서라도 예전에 acc_와 tf_를 이용해서 만든 PLI 모델을 업그레이드해야겠군요. )



int misctf_proc(int data, int reason,int paramvc) {
 
 static int  reset_called = FALSE;
 int   POInt;
 
 
 
 switch (reason) {
  case reason_paramvc : { // 파라미터의 값 변화로 인한 호출의 경우
   if (tf_getp(PIN_RST_X) == 0) { // reset state
    // 아래의 형태는 초기 조건에서의 리셋 호출을 위하여 사용된다.
    if (reset_called == FALSE || paramvc == PIN_RST_X) {
     io_printf(“$AE32KB_RUN : CORE RESET CONDITION\n”);
     // 실제적인 reset을 수행한다.
     
     reset_called = TRUE;
     
     POInt = 0;
     
     if (tf_getp(PIN_OSIEN) == 1) {
      POInt = POInt | OSIEN;
      if (tf_getp(PIN_OSIROM) == 1) {
       POInt = POInt | OSIROM;
      }
     }
     ResetCore(POInt);
    }
   }
   else if ( paramvc == PIN_CLK ) {  
    if (is_posedge(PIN_CLK,paramvc) == TRUE) {
     // 변경된 모든 입력 값을 받아서 반영한다. 
     apply_input();
     io_printf(“%s : CLOCK POSEDGE\n”, tf_strgettime());
     
     EndClock();
     // end_clock함수
     
     StartClock();
     // start clock 함수
     
     // 변경된 데이터를 기반으로 핀과 레지스터를 변경시킨다.
    }
   }
   break;
  }
//  case
  default :
  break;
 }
 
 // apply outputs
 apply_output();
    return 0;
}


이제 EISC processor도 어느 정도 정비를 마치고, 빠른 미래에  좀 더 공격적인 마케팅을 시작할 예정입니다. ^^; 많이 기대를 해 주세요.. 특히 학생분들께 좋은 기회가 많이 돌아가도록 노력 중입니다.

이런 저런 뉴스 모음

전자 엔지니어 뉴스 중 흥미 있는 뉴스 몇 가지..



  • 시높시스, 스웨덴의 ASIC 프로토타이핑 회사 인수
    (http://www.eetkorea.com/ART_8800467221_839575_NT_77236ec4.HTM?click_from=RSS)
    FPGA기반의 ASIC 프로토타이핑 회사란 거의 emulation이 아닌가 싶은데.. 여하튼 빠른 coverage를 위해서 도움이 될 것이라 생각합니다. 지난번 synopsys-verification seminar때 emulator관련 회사가 참석한 것도 이런 맥락이 아닌가 생각되구요

  • 텐실리카, 서울대 SoC 사업단과 한국과학기술원에 엑스텐사 공급
    (http://www.eetkorea.com/ART_8800467058_1134551_NT_5f5961d4.HTM?click_from=RSS)
    텐실리카(Tensilica) Xtensa 프로세서의 선전이 눈부십니다. 🙂 프로세서 하는 입장에서 텐실리카의 방향성은 아주 좋다고 생각하지요. 단지, 저희 회사와 약간 방향이 다르긴 한데.. 이런 기사를 볼때 마다 분발하게 됩니다. 아직까지는 인력이나 방향성이 탄력을 받은 상황이 아니니 비교는 어렵겠습니다만.. 올해부터 향후 3년 동안의 EISC processor를 눈여겨 봐 주십시오 ^^;

  • ARM-LG전자, 2009년 미국 디지털 방송 대비 라이선스 체결
    (http://www.eetkorea.com/ART_8800466903_480703_NT_f5fac31d.HTM?click_from=RSS)
    이 이야기는 선배에게 얼마전에 들었는데, 뉴스화 되었군요. ARM9EJS 프로세서는 상당히 잘 만든 프로세서임에 틀림없습니다. 효과적인 Java지원도 그렇고, 폭 넓은 소프트웨어 지원도 그렇고.. DSP에 있어서는 그리 좋다는 느낌을 받지는 못하고 있는데, 그래도 수많은 3rd party사들이 DSP library를 만들어내고 있으니 아주 부럽죠. 제가 만들고 있는 32bit EISC processor가 ARM9급 시장에 targeting하고 있어서 ARM9EJS와의 benchmark를 가끔해보는데, assembly 코드로 DSP 코딩을 하는 경우(ARM도 assembly로 된 DSP library를 쓰고)에는 동 클럭에서 더 좋게 나오기는 합니다만.. 전반적으로는 ARM9EJS의 클럭 스피드가 높으니, 저희것이 좋다고 할수는 없는 상황이죠. ^^; 국내 업체들의 지원하에 ARM의 시장 지배력이 점차 높아지는 것이 달갑지는 않은 상황입니다. 🙂

  • MIPS, 주목 받는 첨단 IP 코어 발표
    (http://www.eetkorea.com/ART_8800466897_839585_NP_820c116d.HTM?click_from=RSS)
    MIPS에서 새로 나온 MIPS74K이야기인데요.. Microprocessor Report에서도 대대적으로 보도하고 있는데, 가장 큰 이유가 dual issue out-of-order superscalar processor라는 점이에요. 사실 superscalar processor가 embedded에 나타난건 예전부터 있었지요(MIPS 사의.. 음.. 기억이 안나는데..4x던가요? 그넘이 한 5년정에 발표된걸로 기억하고, 얼마전에 ARM의 Cortex A8도 있구요).
    시장은 이제서야 열리는 거 같은데.. 그 동안 in-order형태였는데, 74K는 out-of-order라는 점에서 주목 받는 것이겠습니다. embedded에서 dual issue 이상 가지는 않을 거라 생각해요.. 대부분 benchmark에서 superscalar가 dual issue일때 가장 가격 효율성이 있으니까요.. 🙂

Perl을 이용해서 검증할때 유용한 팁

뭐랄까요.. 요즘 이런 저런 일로 바쁘다보니, 사람이 좀 얇팍하게 글을 쓰게되네요. 🙂
(퇴고 없이 그냥 온라인에서 쓰는 글이라 앞뒤가 없을지도 모르겠습니다.)

오늘은 여러분들께서 perl을 이용해서 Verilog HDL을 위한 testbench를 작성할 때 간단히 명령어 해석기를 만들어 사용하는 방법을 알려드리죠.

이 방법은 제가 JTAG을 위한 protocol을 만들다가 생각해낸 방법인데요.. 아주 유용하게 쓰고 있습니다.
얼마전 AXI FileReader와 같은 간단한 명령어 해석기가 필요할 때도 쉽게 적용할 수 있구요.

예를들어, JTAG을 위한 몇몇 명령을 만들고, 이 명령을 이용해서 HDL model을 위한 신호 입력으로 변환시키는 과정을 생각해 봅시다.

1. 필요한 함수를 정합니다.
대충 다음과 같은 함수를 쓸 수 있겠지요?


rtnval = get_id();
do_intest(serin);
do_extest(serin);


2.
해당 함수를 perl에서 subroutine으로 만들어갑니다.
뭐, subroutine을 만드는 방법은 쉽죠?

3.
이 부분이 제일 중요한데요..


xxx.pl <filename.input>

이런식으로 처리하려면, 중간에 다음과 같은 루틴을 넣어줍니다.


do “$ARGV[0]”;

위의 한 행은 해당 파일($ARGV[0])에 지정된 “perl” 명령어들을 읽어와서 해석하는 부분입니다.
즉, 여러분께서 “filename.input” 이라는 입력 파일에 앞에서 작성한 subroutine을 “명령어 사용하듯” 적어두면, 이것이 perl script에서 읽혀서, “명령어를 해석하듯” 동작하게 됩니다.
이렇게 함으로써, 파싱하는 부분을 생략하고도, 그럴듯하게 명령어 해석기처럼 하나의 perl 스크립트를 만드는 것이 가능합니다.

이제 이러한 perl script에서 어떻게 HDL 테스트 벡터를 만들어내는지 생각해 봅시다.
간단히 생각할 수 있는 것은 두 가지 인데요.
첫번째는 ROM file형태로 만들어버리고, verification을 위한 testbench에서는 $readememh()를 써서 읽은 다음에 한 클럭에 하나의 신호 그룹을 뿌리는 방법이구요..
두번째는 각 subroutine에 printf FOUT 과 같은 file output을 사용해서, 간단한 verilog testvector를 만들어내고, 이를 verification을 위한 testbench에서 `include “xxx” 명령을 이용해서 읽어들이는 방법입니다.

둘 다 간단하죠?

한 마디로, perl을 이용하면 C로는 어렵게 해야 할 일이 아주 아주 편해지는 일이 많습니다. 그래서 verification engineer들에게 perl과 같은 scripting 언어가 사랑받는 것이겠죠.