ASIC SoC2010. 12. 2. 15:37

The Example Design



 

Memory Map

 
사용자 삽입 이미지

 메모리 맵은 위와 같습니니다.
 Instruction Memory (ROM)은 0x0400_0000에 위치합니다.
 부팅시에 부팅 코드를 SRAM으로 카피하고 움직이게 됩니다.

 Interrupt Assignments

 
 OpenRISC 1000은 프로그래머블한 인터럽트 코아를 가지고 있고, 외부에서 20개의 인터럽트를 연결할 수 있습니다. 그중에서 사용하는 인터럽트는 아래와 같이 배치되어 있습니다.

사용자 삽입 이미지

Test Bench Modeling of Peripherals


Peripherals들은 모델링이 되어 있지 않습니다
외부 포트들은 모두 적당한 값으로 매핑되어 둡니다.

ORPSoC의 트래킹은 OpenRISC 100의 l.nop 명령어를 활용하여서 내부 정보를 얻어냅니다.
l.nop 명령은 immediate 값을 가질 수 있는데 이 값에 적당한 값을 할당 함으로서 원하는 동작을 수행합니다.

여기서 사용하는 방식은 아래 테이블에 정리되어 있다.

사용자 삽입 이미지
 다른 l.nop의 인자는 모두 무시합니다.
 testbench 구현은 이 새로운 l.nop 명령을 활용하여 구현하게 됩니다.
 

Test Software Application


Test Application은 Dhrystone 2.1 벤치마크 프로그램을 활용합니다.
앞서 설명한 n.lop 명령을 활용하여 라이브러리 중 일부룰 수정하여서 필요한 정보를 프린트하거나 얻게 됩니다.

OpenRISC 1000의 l.nop 명령어 사용하기

앞서 설명했듯이 l.nop명령은 16비트의 immediate 값을 가지고 움직입니다.
이 값은 CPU에서는 무시되지만, 테스트 벤치에 의해서 모니터링 되고 사용됩니다.
이 ORPSoC에서는 이것을 이용해서 I/O를 제공하고, C Code가 운용될 때 내부 정보를 얻을 수 있는 컨트롤 함수의 기능을 구현하는 활용합니다.

l.nop 1  : 32'h1500_0001
    GPR3에 있는 값을 리턴코드로 하여 프로그램을 끝냅니다.
    C Lib 함수는 다음과 같이 구현됩니다.

void exit (int i)
{
  asm("l.add r3,r0,%0": : "r" (i));
  asm("l.nop %0": :"K" (NOP_EXIT));
  while (1);
}



l.nop 2  : 32'h1500_0002
    GPR 3의 값을  Hex로 덤프하여 줍니다.

l.nop 3  : 32'h1500_0003
    printf을 지원해 주지만 아직까지는 제대로 구현이 안되어 있다.

l.nop 4  : 32'h1500_0004
    LSB를 Character로 프린트 해줍니다.
    PUTC를 구현하는 것은 아래와 같습니다.

void putc(int value)
{
  asm("l.addi\tr3,%0,0": :"r" (value));
  asm("l.nop %0": :"K" (NOP_PUTC));
}
	  
   이것을 이용해서 나중에 printf등을 구현할 수 있을 겁니다.




Posted by GUNDAM_IM
ASIC SoC2010. 12. 2. 15:37

High Performance SoC Modeling with Verilator


이번에 정리하는 것은 Verilator를 이용해서 OpenRISC 프로세서를 시뮬레이션하는 것입니다. 기본적인 플로우는 ICARUS라는 GNU Verilog 시뮬레이터 환경을 바꾸어서 진행하는 것입니다.

관련한 원본 자료는 아래 페이지에 있습니다.

http://www.embecosm.com/download/ean6.html

진행하는 플랫폼은 MAC이지만, Verildator는 Platform Independent하므로 대부분의 플랫폼에서 작동할 것으로 생각됩니다.

플랫폼별 차이점이 있다면, 나중에 기회가 되면 정리하겠습니다.
- 즉 귀찮아서 하지 않을 수도 있다는 의미입니다.

전제 사항들...


(1) Verilator를 설치하고 테스트 하는 방법은 앞서 정리한 블로그 자료를 참조하시기 바랍니다.
     역시 플랫폼 독립적이므로, 다른 플랫폼에서도 거의 비슷하게 동작할 것입니다.
    
(2) Linux 혹은 MAC의 터미널 환경에 대해서 잘 알고 있다는 가정하에서 설명이 진행됩니다.


다른 책에도 맨날 나오는 내용이지만,  S/W와 하드웨어의 파티셔닝과 그에 다른 시스템의 성능 평가가 중요한 부분인지에 대한 설명입니다.


시스템의 성능에 대해서 정밀한 분석은 하드웨어와 그 하드웨어에 의해서 움직일 임베디드 소프트웨어에 기반합니다.

로레벨의 BSP나 디바이스 드라이버 같은  Embedded Firmware의 구현은 SoC Peripheral의 정확한 동작에 기반하여 구현됩니다.

소프트웨어의 최적화. 이것은 Codec  개발에서 특히 중요한 부분입니다.  특히 이 것은 프로세서와 메모리 캐쉬 MMU등의 상호간 동작에  아주 깊은 영향을 받습니다. 따라서 ISS와 TLM은  잘못된 결과를 도출하는 것을 방지하여 줍니다.


Modeling Language


   Verilator는 Verilog를 C/C++로 변환하여서 컴파일하게 됩니다.
  당연히 C++ 컴파일러의 최적화 효율에 영향을 받게 됩니다.
  그리고 64비트 시스템 환경에서 더 빨리 운용이 됩니다.

OpenRISC는

  www.opencores.org에서 여러명이 설계한 프로세서 입니다.
  명령어 체계상에서는 32비트 외에도 64비트나 DSP등도 있습니다.
  최근에는 좀더 performance를 올린 프로세서를 만드는 프로젝트도 시작하고 있습니다.
  국내외에서 알게 모르게 여러 IP내부 프로세서나 SoC 프로세서로 사용하고 있습니다.

  OpenRSIC 1000은 Verilog로 만들어진 프로세서를 의미하고
  OpenRISC 1200은 OpenRISC Core + SoC Platform을 의미합니다. 완전한 SoC 플랫폼이며, 줄여서 ORPSoC라고 합니다.  

   OpenRISC 1000은 Processor외에도 CACHE나 MMU등을 가지고 있습니다.
  관심을 가질만한 부분은 l.nop라고 하는 nop 명령어입니다. 이 명령어는 하위에 immediate field를 가지고 있는데 이 field를 이용해서 몇가지 옵션을 주고 운용하는 기능을 부여할 수 있습니다. 일종의 MIPS의 Instruction Extension 기능인 UDP 기능을 생각하시면 됩니다.
  여기서는 Simulation시에 몇가지 특수 용도로 사용하지만,  실제 하드웨어에는 영향을 주지 않습니다.
 

The OpenRISC Reference Platform System-on-Chip (ORPSoC)



사용자 삽입 이미지

OPRSo의 전체 구조는 위와 같습니다.
전체 크기는 15만 게이트에 메모리 별도입니다.
이 회로는 Xilinx나 Altera의 FPGA 보드에서 잘 동작합니다.

OPRSoC에는 Flash Memory가 2MB 붙어 있고, 2MB의 SRAM이 연결되어 있습니다.
그외의 메모리는 FlipFlop 스타일 (SRAM스타일) 의 I/F를 가지고 있습니다.

   

 




Posted by GUNDAM_IM
ASIC SoC2010. 11. 13. 11:22
이번에는 verilator로 실행하여서 vcd파일을 덤프하는 것을 만들어 보겠습니다.

일단 verilator로 c++ 소스 코드를 빌드할 때 이전과 차이점은  --trace 옵션이 붙습니다.

verilator --cc  --trace --exe dff_sync_reset_main.cpp  dff_sync_reset.v

위와 같이 실행하여서 Makefile과 c++ 코드를 만들어 냅니다.

testbench격인  dff_sync_reset_main.cpp 역시 수정해야 합니다.

#include <stdlib.h>
#include<iostream>

#include <verilated.h>          // Defines common routines
#include "verilated_vcd_c.h"
#include "Vdff_sync_reset.h"               // From Verilating "top.v"

......

int main(int argc, char** argv) {
            Verilated::commandArgs(argc, argv);   // Remember args

            Verilated::traceEverOn(true);
            VerilatedVcdC* tfp = new VerilatedVcdC;


            dff_sync_reset = new Vdff_sync_reset;             // Create instance

            dff_sync_reset->trace (tfp, 99);
            tfp->open ("./simx.vcd");

            dff_sync_reset->reset = 0;           // Set some inputs

            cout << "Start Simulation" << endl;

            while (!Verilated::gotFinish()) {
                if (main_time > 10) {
                    dff_sync_reset->reset = 1;   // Deassert reset
           .........
                main_time++;            // Time passes...

                tfp->dump (main_time);

            }
            dff_sync_reset->final();               // Done simulating
            //    // (Though this example doesn't get here)
            tfp->close();
            cout << "End Simulation" << endl;
}

추가되는 코드는 위와 같습니다.

먼저 헤더 파일로
#include "verilated_vcd_c.h"
을 읽어들이도록 합니다. 이것은 vcd 덤프를 위한 정보가 들어있습니다.

그리고 trace를 on하고
dump파일을 생성합니다.

            Verilated::traceEverOn(true);
            VerilatedVcdC* tfp = new VerilatedVcdC;
...
            dff_sync_reset->trace (tfp, 99);
            tfp->open ("./simx.vcd");

위에서 traceEverOn은 Trace를 항상 한다는 의미이고
dff_sync_reset->trace(tfp,99)는  최상위 모듈에서 밑으로 99개 depth까지 추적한다는 의미입니다.
거의 무한대겠군요

이후에

tfp->open(...)

을 호출하여 파일을 생성합니다.

            while (!Verilated::gotFinish()) {
                if (main_time > 10) {
                    dff_sync_reset->reset = 1;   // Deassert reset
           .........
                main_time++;            // Time passes...

                tfp->dump (main_time);

            }

무한 루프를 돌면서 한 턴이 끝나면 모두 save할 수 있도록 dump함수를 호출합니다.

이후에 시뮬레이션이 끝나면
            tfp->close();
으로 화일을 닫습니다.

이렇게 해서
simx.vcd
라는 파일을 얻어냅니다.
이것을 vcd 파일 볼 수 있는 프로그램인 gtkwave라던가 scansion에서 불러들이면 됩니다.

개인적으로는 맥스러운 GUI라면 Scansion인데 이 scansion에서 약간의 버그가 있습니다.
vcd파일에서 각 행의 시작열에 공백이 있으면 버그로 인식하게 됩니다.
이 프로그램은 잘 안팔려서 그런지 업데이트가 아주 느립니다.

요부분은 수작업으로 바꾸거나
스크립트로 바꾸면 됩니다.


=== Before ===
$version Generated by VerilatedVcd $end
$date Sat Nov 13 11:15:57 2010
 $end
$timescale 1ns $end

 $scope module TOP $end
  $var wire  1 $ clk $end
  $var wire  1 # data $end
  $var wire  1 & q $end
  $var wire  1 % reset $end
  $scope module v $end
   $var wire  1 $ clk $end
   $var wire  1 # data $end
   $var wire  1 & q $end
   $var wire  1 % reset $end
  $upscope $end
 $upscope $end
$enddefinitions $end


=== After ===
$version
   Generated by VerilatedVcd
$end
$date
    Sat Nov 13 10:51:15 2010
$end
$timescale
    1ns
$end

$scope module TOP $end
$var wire  1 $ clk $end
$var wire  1 # data $end
$var wire  1 & q $end
$var wire  1 % reset $end
$scope module v $end
$var wire  1 $ clk $end
$var wire  1 # data $end
$var wire  1 & q $end
$var wire  1 % reset $end
$upscope $end
$upscope $end
$enddefinitions $end
...

위와 같이 첫번째 열들부터 나타나는 공백을 모두 지우고 불러들이면 됩니다.

사용자 삽입 이미지

그리고 일일이 스크립트를 돌리기  귀찮으면verilator 소스 코드를 직접 수정하면 됩니다.
ident에 관한 일이므로 verilator 스타일로 보건데 한군데서 다 처리할 것 같아 뒤져보았습니다.

일단,
verilator source code가 있는 폴더에서 다음 파일을 찾아서 정리합니다.
.
...../verilator-3.804/include/verilated_vcd_c.cpp

이 파일에서 void VerilatedVcd::dumpHeader ()  함수가 헤더를 덤프해주는 함수입니다.
이 함수 내에 있는 printIdent(xxx) 함수 호출에서 xxx 부분을 몽땅 0으로 바꾸어 주면 됩니다.

=== before ===
354 행 :  printIndent(1);
=== after  ===
              printIndent(0);


382행
=== before ===
 printIndent(-1);
=== after ==
 printIndent(0);

392행
=== before ===
 printIndent(1);
=== after ==
 printIndent(0);


407행
=== before ==
printIndent(-1);
=== after ===
printIndent(0);

411행
=== before ====
printIndent(-1);
=== after ===
printIndent(0);

으로 변경합니다.
결론적으로 해당 함수의 printIdent는 모두 0으로 만들어버리면 ident가 VCD 파일에 들어가지 않습니다.
이제 새롭게 컴파일해서 설치하면 앞서의 scansion에서 파일 오픈할 때 일일이 헤더 부분을 수정할 수고를 덜어줍니다. 어차피 VCD파일 내부를 누가 보겠습니까 ?  IDENT가 없다고 상관없겠죠

이제 일일이 스크립트 돌릴 필요 없이 그냥 출력 파일을  scansion 에서 읽어들일 수 있습니다.







Posted by GUNDAM_IM
ASIC SoC2010. 11. 13. 10:26
이전에 정리한 글에서 tesebench에 해당하는 부분을 정리합니다.

verilator를 거쳐서 빌드한 소스코드에는 다음과 같은 파일들이 생성됩니다.

GUNDAM-NT:obj_dir kevinim$ ls
Vdff_sync_reset.cpp           Vdff_sync_reset.mk            Vdff_sync_reset__Syms.h       Vdff_sync_reset__verFiles.dat
Vdff_sync_reset.h             Vdff_sync_reset__Syms.cpp     Vdff_sync_reset__ver.d       Vdff_sync_reset_classes.mk

위의 코드에서 중요한 것은  헤더 파일인 Vdff_sync_reset.h 파일입니다.
내용을 보면

#ifndef _Vdff_sync_reset_H_
#define _Vdff_sync_reset_H_

#include "verilated.h"
class Vdff_sync_reset__Syms;

//----------

VL_MODULE(Vdff_sync_reset) {
  public:
    // CELLS
    // Public to allow access to /*verilator_public*/ items;
    // otherwise the application code can consider these internals.

    // PORTS
    // The application code writes and reads these signals to
    // propagate new values into/out from the Verilated model.
    VL_IN8(clk,0,0);
    VL_IN8(data,0,0);
    VL_IN8(reset,0,0);
    VL_OUT8(q,0,0);

    // LOCAL SIGNALS
    // Internals; generally not touched by application code

    // LOCAL VARIABLES
    // Internals; generally not touched by application code
    VL_SIG8(__Vclklast__TOP__clk,0,0);
    //char      __VpadToAlign13[3];
....

코드의 중간에 입출력 신호로 clk,daa,reset,q가 선언되어 있는 것을 볼 수 있습니다.
대략 통밥으로 굴리면 매크로만 보아도 8비트  char 타입으로 선언된것을 알 수 있습니다. ㅋㅋ
전체적으로는 클래스를 선언하고 입출력 포트는 해당 타입에 맞는 변수로 선언하는 것을 알 수 있습니다.
-  원래 C++로 하면 이렇게 밖에 할 수 없죠..
입출력 변수들은  public 에 위치시키고 있습니다.

그러면 이렇게 선언된 입출력 변수들을 main에서 access하기위해서는
class의 public 변수 참조 방식을 그대로 사용합니다.

#include "Vdff_sync_reset.h"
...
Vdff_sync_reset *dff_sync_reset;
...
 dff_sync_reset = new Vdff_sync_reset;
....
                if (( main_time % 10) == 1) {
                    dff_sync_reset->clk = 1;       // Toggle clock
                }
                if (( main_time % 10) == 6) {
                    dff_sync_reset->clk = 0;
                }
...

위와 같이 합니다. 일단 header파일을 인쿨루드 한 후에
module의 포인터를 선언하고
new로 해당 모듈을 생성합니다.

나머진 모듈(클래스)의 public값 쓰듯이 작업하면 됩니다.

testbench 격인 C++코드는 아래와 같은 구조로 되어 있습니다.

double sc_time_stamp () {       // Called by $time in Verilog
        return main_time;
}
        
int main(int argc, char** argv) {
            Verilated::commandArgs(argc, argv);   // Remember args
            dff_sync_reset = new Vdff_sync_reset;             // Create instance
            
......
            cout << "Start Simulation" << endl;  

            while (!Verilated::gotFinish()) {
  ........
                main_time++;            // Time passes...
            }
            dff_sync_reset->final();               // Done simulating
            //    // (Though this example doesn't get here)
            cout << "End Simulation" << endl;
}

main_time 변수는 verilog에서 $time을 호출할 때 반환되는 변수입니다.
verilog에서 $time을 호출하면 sc_time_stamp를 호출하게 되고 이때 main_time을 반환합니다.

main함수는
  초기화 블럭과
  무한 루프 블럭으로 나누어집니다.
   
  초기화 블럭은 시스템의 입출력 값을 초기화 시키는 것을 먼저 하고
  무한 루프 블럭에서 이리저리 한 작업을 계속 하게 됩니다.
  지정된 조건에 부합되면 무한 루프를 빠져나오면 되고요,
  만약 Verilog 에서 $finish를 호출하게 되면

  Verilated::gotFinish()

  에서 true를 돌려주게 되어 루프를 빠져나가게 됩니다.
  이후 작업은 finsh작업에 해당합니다.








Posted by GUNDAM_IM
ASIC SoC2010. 11. 13. 10:11
맥을 가진자의 숙명으로 그런 저런 불편함을 감수하면서 살아가고 있는 중에
몇일전에 날라온 메일을 보다가 발견한것이 Verilog 시뮬레이터인 Verilator입니다.
VCS라던가 다른 넘들처럼 Cycle Based Simulation 을 진행하여
엄청 빠른것을 자랑하고 있습니다. 흠...
여타 RTL 시뮬레이터 보다 2~30배 빠르다는 둥 하여튼 열심히 이야기하고 있길래 한번 사용해보고 사용법을 정리하였습니다.

Verilator는 엄밀하게는 시뮬레이터가 아니고 Verilog, SystemVerliog 등을 SystemC나 C++등으로 변환시켜주는 툴입니다. 실행파일로 만들어주니까 빠르게 된다는 것을 장점으로 삼고 있습니다.


(1) 설치하기
   
     설치하려면 gmake등이 필요합니다.
     일단 gmake는
 
     su port install gmake

    하고 루트 암호를 넣어주면 잘 설치가 됩니다.
 
    verilator는 아래 사이트에서 다운 받습니다.

   http://www.veripool.org/

   압축을 풀고 다음과 같이 진행합니다.

   ./configure
   gmake
   make test
   sudo make install

   차례로 치면 컴파일과 설정이 됩니다.

   체크는  
   
   verilator --help

   하면 쭈욱 화면에 프린트가 됩니다.

(2) 빠른 부분에 대한 설명

   홈페이지에 보면 아래와 같이 되어 있습니다. VCS대비 1.5배 NC-Verilog 대비 3배 빠르다고 나옵니다.

  • Verilator is 90x faster than Icarus Verilog.
  • Verilator is 10-40x faster than Modelsim SE.
  • Verilator is 3x faster than NC-Verilog.
  • Verilator is 1.5x faster than VCS.
  • VTOC is 4x faster than Verilator.
  • VTOC is 50x faster than NC-Verilog.
  • VCS is 3x faster than Verilator.
  • VCS is 3x faster than NC-Verilog.
  • VCS is 10x faster than NC-Verilog.
  • VCS is the same speed as NC-Verilog.
  • CVer is the same speed as Icarus Verilog.
 
   이렇게 빠른것은 Verilog Simulator가 아니라 Verilog Compiler입니다.
   verilog 코드를 받아 들여서

   C++이나 SystemC, SystemPerl ( 이건 왜나오는건지.. ) 등으로 바꾸는 역활을 합니다.

(3) 사용법에 대해서는....
    
    두단계로 나누어서 작업합니다.
   
    일단 Verilog Code가 완성 된 뒤에
    testbench에 해당하는 main.cpp를 만들어 둡니다.

    (1) C++ 코드로 만들기
         verilator는 시뮬레이터가 아니라 verilog를 c++등으로 바꾸어주는 translator에 가깝습니다.
        
         verilator를 이용해서 C++을 만들어 가는 것이 첫번째 작업입니다.

    (2) C++ 코드 빌드하기
        만들어진 코드는 obj_dir 이라는 폴더에 생깁니다.
        이 폴더에 보면 make파일이 생성되는데 이 make파일을 이용해서 실행 화일을 빌드하는 것이
       두번째 작업입니다.
        
    
  사용될 verilog code는 아래와 같습니다.
  간단한 DFF의 예제입니다.

//-----------------------------------------------------
// Design Name : dff_sync_reset
// File Name   : dff_sync_reset.v
// Function    : D flip-flop sync reset
// Coder       : Deepak Kumar Tala
//-----------------------------------------------------
module dff_sync_reset (
data   , // Data Input
clk    , // Clock Input
reset  , // Reset input
q        // Q output
);
//-----------Input Ports---------------
input data, clk, reset ;

//-----------Output Ports---------------
output q;

//------------Internal Variables--------
reg q;

//-------------Code Starts Here---------
always @ ( posedge clk)
if (~reset) begin
  q <= 1'b0;
end  else begin
  q <= data;
end

endmodule //End Of Module dff_sync_reset

 인터넷에서 구할 수 있는 간단한 dff의 예제입니다.
 
 자세한 설명은 나중에 하고 testbench에 대한 코드는 아래와 같습니다.

#include <verilated.h>          // Defines common routines
#include "Vdff_sync_reset.h"               // From Verilating "top.v"

Vdff_sync_reset *dff_sync_reset;                      // Instantiation of module
unsigned int  main_time = 0;     // Current simulation time

double sc_time_stamp () {       // Called by $time in Verilog
        return main_time;
}
        
int main(int argc, char** argv) {
            Verilated::commandArgs(argc, argv);   // Remember args
            dff_sync_reset = new Vdff_sync_reset;             // Create instance
            
            dff_sync_reset->reset = 0;           // Set some inputs

            cout << "Start Simulation" << endl;  

            while (!Verilated::gotFinish()) {
                if (main_time > 10) {
                    dff_sync_reset->reset = 1;   // Deassert reset
                }
                if (( main_time % 10) == 1) {
                    dff_sync_reset->clk = 1;       // Toggle clock
                }
                if (( main_time % 10) == 6) {
                    dff_sync_reset->clk = 0;
                }
                dff_sync_reset->eval();            // Evaluate model
                //cout << "Output : " << hex << dff_sync_reset->q << endl;       // Read a output
                printf("SIM %010d : (reset) %d, (clk) %d, (data) %d , (q) %d\n", main_time ,                                                    dff_sync_reset->reset ,  
                                                  dff_sync_reset->clk,
                                                  dff_sync_reset->data,
                                                  dff_sync_reset->q );
                main_time++;            // Time passes...
 
                if( main_time == 20) dff_sync_reset->data = 1 ;
                if( main_time == 80) dff_sync_reset->data = 0 ;
                if( main_time > 100) break;

            }
            dff_sync_reset->final();               // Done simulating
            //    // (Though this example doesn't get here)
            cout << "End Simulation" << endl;
}

 verilog code의 파일명은 dff_sync_reset.v 이고
c++ 테스트 벤치 코드는 dff_sync_reset_main.cpp 으로 지정해 둡니다.

그리고 make파일을 만드는 명령은 아래와 같습니다.

verilator --cc  -exe dff_sync_reset_main.cpp  dff_sync_reset.v

--cc 옵션은 c++ 형태로 코드를 만들어 돌라는 의미입니다.
-exe 옵션은 실행 파일로 만들어 돌라는 옵션입니다.
       이 옵션이 없으면 .a 파일인 라이브러리 파일로 만들어집니다.
       이 옵션을 주게 되면 main() 함수를 찾게 되는데 이 것으 없으면 나중에 컴파일 시에 오류가 발생합니다.
       따라서 main()함수가 포함된 .cpp파일을  --exe 옵션 뒤에 명시합니다.

그러면 obj_dir 폴더가 만들어집니다.

GUNDAM-NT:test kevinim$ cd obj_dir/
GUNDAM-NT:obj_dir kevinim$ ls
Vdff_sync_reset.cpp           Vdff_sync_reset.mk            Vdff_sync_reset__Syms.h       Vdff_sync_reset__verFiles.dat
Vdff_sync_reset.h             Vdff_sync_reset__Syms.cpp     Vdff_sync_reset__ver.d        Vdff_sync_reset_classes.mk

해당 되는 폴더에 들어가면 위와 같은 파일들이 있습니다.

나머지 파일은 넘어가고 .mk 파일이 make 파일입니다.

빌드는 아래와 같이 수행합니다.


GUNDAM-NT:obj_dir kevinim$ make -f Vdff_sync_reset.mk
g++  -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -c -o dff_sync_reset_main.o ../dff_sync_reset_main.cpp
g++  -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -c -o verilated.o /usr/local/share/verilator/include/verilated.cpp
/opt/local/bin/perl /usr/local/share/verilator/bin/verilator_includer Vdff_sync_reset.cpp > Vdff_sync_reset__ALLcls.cpp
g++  -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -c -o Vdff_sync_reset__ALLcls.o Vdff_sync_reset__ALLcls.cpp
/opt/local/bin/perl /usr/local/share/verilator/bin/verilator_includer Vdff_sync_reset__Syms.cpp > Vdff_sync_reset__ALLsup.cpp
g++  -I. -MMD -I/usr/local/share/verilator/include -I/usr/local/share/verilator/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -c -o Vdff_sync_reset__ALLsup.o Vdff_sync_reset__ALLsup.cpp
      Archiving Vdff_sync_reset__ALL.a ...
ar r Vdff_sync_reset__ALL.a Vdff_sync_reset__ALLcls.o Vdff_sync_reset__ALLsup.o
ar: creating archive Vdff_sync_reset__ALL.a
ranlib Vdff_sync_reset__ALL.a
g++    dff_sync_reset_main.o verilated.o Vdff_sync_reset__ALL.a    -o Vdff_sync_reset -lm -lstdc++  2>&1 | c++filt

  이상 없이 빌드 되었으면 실행하면 됩니다.

GUNDAM-NT:obj_dir kevinim$ ./Vdff_sync_reset
Start Simulation
SIM 0000000000 : (reset) 0, (clk) 0, (data) 0 , (q) 0
SIM 0000000001 : (reset) 0, (clk) 1, (data) 0 , (q) 0
SIM 0000000002 : (reset) 0, (clk) 1, (data) 0 , (q) 0
SIM 0000000003 : (reset) 0, (clk) 1, (data) 0 , (q) 0
SIM 0000000004 : (reset) 0, (clk) 1, (data) 0 , (q) 0
SIM 0000000005 : (reset) 0, (clk) 1, (data) 0 , (q) 0
SIM 0000000006 : (reset) 0, (clk) 0, (data) 0 , (q) 0
....

대충 움직이는 것을 확인해 볼 수 있습니다.

다음번에는 wave로 덤프하는 것을 추가해보도록 하겠습니다.


        

    

Posted by GUNDAM_IM