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
ASIC SoC2010. 10. 30. 20:39
간만에 다시 하는 코딩을 위해서
이번에는 Emacs에서 Verilog 를 사용하고 해보기로 했습니다.
- 작년에는 거의 Verilog Template language + Perl Stript Compiler만을 사용해서 이넘을 사용해 보고 싶었지만, 사용해볼 기회가 별로 없었기 때문입니다.


Emacs에서 Verilog Mode를 사용하는 것은
VHDL Mode보다는 조금 불편한데요.. 특히 Template기능이 VHDL에 비해서 약해서 그렇습니다.

VHDL은 거의 Editer + Template수준으로 만들어 내었는데 Verilog는 Syntax Highlite 기능으로만
버텨왔기 때문입니다.

요새는 많이 좋아져서 어느정도 자동화 기능을 백그라운드로 돌리면서 에디팅을 할 수 있도록 지원해주고 있습니다.

그런 기능을 활용하기 위해서는 verilog mode를 설치해야 합니다.

http://www.verilog.com/emacs_install.html

위 사이트에 가면 알수 있습니다.
최신 Linux에서는 verilog mode를 디폴트로 가지고 오는데 MAC은 없는 관계로 위의 사이트의 내용을 참조로 해서 수정해야 운용이 가능합니다.

루트 폴더에서 .emacs 파일을 만들어서
다음과 같은 내용을 넣어 둡니다.

------------- BEGIN ----
(defun prepend-path ( my-path )
(setq load-path (cons (expand-file-name my-path) load-path)))

(defun append-path ( my-path )
(setq load-path (append load-path (list (expand-file-name my-path)))))
;; Look first in the directory ~/elisp for elisp files                                                                        
(prepend-path "~/elisp")

;; Load verilog mode only when needed                                                                                        
(autoload 'verilog-mode "verilog-mode" "Verilog mode" t )

;; Any files that end in .v, .dv or .sv should be in verilog mode                                                            
(add-to-list 'auto-mode-alist '("\\.[ds]?v\\'" . verilog-mode))

;; Any files in verilog mode should have their keywords colorized                                                            
(add-hook 'verilog-mode-hook '(lambda () (font-lock-mode 1)))

;;; User customization for Verilog mode                                                                                      
 (setq verilog-indent-level             3
       verilog-indent-level-module      3
       verilog-indent-level-declaration 3
       verilog-indent-level-behavioral  3
       verilog-indent-level-directive   1
       verilog-case-indent              2
       verilog-auto-newline             t
       verilog-auto-indent-on-newline   t
       verilog-tab-always-indent        t
       verilog-auto-endcomments         t
       verilog-minimum-comment-distance 40
       verilog-indent-begin-after-if    t
       verilog-auto-lineup              'declarations
       verilog-highlight-p1800-keywords nil
       verilog-linter                   "my_lint_shell_command"
       )
---------------- END ------------
Verilog-linter는 아직 LINT해주는 툴을 OSX에서 최근에 발견했지만, 아직 테스트 하지 못해서 그냥 냅두었습니다.

사용법은 생각보다 쉽습니다.

중요한 요소에다가 Comment 처리된
/*AUTOXXXX*/
를 넣어두고

코딩이 끝나면

Control-C Control-Z

를 하면 됩니다.

예는 아래와 같습니다.
사용자 삽입 이미지












위와 같이 중요 포인트에 /*AUTOXXX*/ 를 넣고
Ctrl-C Ctrl-Z
를 넣으면

아래와 같이 변합니다.

사용자 삽입 이미지




























위에서
always @ (/*AUTOSENSE*/)
를 하여지만 약어로
always @ (/*AS*/)

하여도 됩니다.

위에서 안보이는 것으로는 /*AUTORESET*/ 기능입니다.

   always @ (posedge clk)
   if ( reset ) begin
       /*AUTORESET*/
   end
   else begin
      a <= b;
   end

위의 코드를 가지고 Ctrl-C Ctrl-Z를 하면

   always @ (posedge clk)
   if ( reset ) begin
       /*AUTORESET*/
       // Beginning of autoreset for uninitialized flops                                                                      
       a <= 1'h0;
       // End of automatics                                                                                                  
   end
   else begin
      a <= b;
   end

으로 뒤져서 초기화가 안되는 변수에 대해서 리셋 구문을 자동으로 해줍니다.

그외에


AUTOASCIIENUM

AUTOINOUTMODULE

AUTOTIEOFF

AUTOUNUSED

AUTOINSERTLISP

AUTO_TEMPLATE

AUTOINSTPARAM


과 같은 AUTOx가 있습니다.


이중에서 AUTOASCIIENUM이 좋은넘인데요

Verilog는 VHDL과 틀려서 변수를 Char로 표시하는 것이 만만찮습니다.

ENUM String을 지원하지 않아서 생긴 문제입니다.

이것때문에 디버깅시에 머리속에서 상수값을 다시 ASCII로 변환하면서 일일이 디버깅해야 하는데

요런 문제를 해결하기 위해서 나온 AUTOx가 AUTOASCIIENUM 입니다.


//== State enumeration
parameter [2:0] // synopsys enum state_info
SM_IDLE = 3'b000,
SM_SEND = 3'b001,
SM_WAIT1 = 3'b010;

//== State variables
reg [2:0] /* synopsys enum state_info */
state_r; /* synopsys state_vector state_r */
reg [2:0] /* synopsys enum state_info */
state_e1;

//== ASCII state decoding
/*AUTOASCIIENUM("state_r", "_stateascii_r", "sm_")*/

위의 코드를 AUTOx로 변환시키면


//== ASCII state decoding
/*AUTOASCIIENUM("state_r", "_stateascii_r", "sm_")*/
// Beginning of automatic ASCII enum decoding
reg [39:0] _stateascii_r; // Decode of state_r
always @(state_r) begin
casex ({state_r}) // synopsys full_case parallel_case
SM_IDLE: _stateascii_r = "idle ";
SM_SEND: _stateascii_r = "send ";
SM_WAIT1: _stateascii_r = "wait1";
default: _stateascii_r = "%Erro";
endcase
end
// End of automatics


위와 같이 됩니다. 따라서 state_r이라는 값을 모니터링하면 현재 상테를 추적해 갈 수 있습니다.


--------------------------------


요새 거의 뜸했던

간만에 하는 ASIC 관련 포스팅이었습니다.


'ASIC SoC' 카테고리의 다른 글

맥에서 Verilog Simulation 하기 (2)  (0) 2010.11.13
맥에서 Verilog Simulation 하기  (0) 2010.11.13
사상 최강의 보드  (2) 2010.04.18
[MIPS] MIPS assembler simulator XSPIM  (8) 2010.03.21
HD Quad Display/Processing Engine  (1) 2010.03.12
Posted by GUNDAM_IM
ASIC SoC2010. 4. 18. 15:00
Xilinx Vertex 6 760을 4개 사용하는 보드

도전해 볼만한 과제인데,

그동안 만든 보드 중에서는 사상 최강의 보드가 될듯..
 FPGA도 못구하지만 , 일단 보드 설계 부터 준비해야 하는 상황..

제작 기간 x 년
연인원    xx 명
스펙터클 + 쓰릴러 * 심리 추리물 = 환상의 3D 아바타 보드..
(주 : 요기서 3D는 3차원 그래픽이 아닌 3D업종의 3D 임)

암튼 동작한다면, 그동안 만든 보드중 최강의 보드가 될 듯 합니다.

후후훗...

보드도 보드지만, 그안에 넣을 회로 설계는..  설계하다가 미쳐갈듯..



'ASIC SoC' 카테고리의 다른 글

맥에서 Verilog Simulation 하기  (0) 2010.11.13
EMACS에 Verilog Mode 설치하고 활용하기  (2) 2010.10.30
[MIPS] MIPS assembler simulator XSPIM  (8) 2010.03.21
HD Quad Display/Processing Engine  (1) 2010.03.12
Sound Effect Processor  (0) 2010.02.01
Posted by GUNDAM_IM
ASIC SoC2010. 3. 21. 20:05
Computer archiecture 서적의 바이블인 Computer organization and design 에 보면
부록에서 SPIM이라는 MIPS Processor 시뮬레이터에 대한 언급이 나옵니다.

Assembler로 코딩한 것을 테스트 해 볼 수 있는 시뮬레이터입니다.
최신 버전이 8 이고 아래 사이트에 가면 다운로드 할 수 있습니다.


소스 코드로 다운로드할 수 있는데 빌드는 크게 어려운 점이 없으므로 쉽게 할 수 있습니다.

사용자 삽입 이미지

특징은 다른 시뮬레이텨들은 대부분 Binary 파일을 로드해서 사용하도록 되어 있는데 이 XSPIM/SPIM은 assembler파일을 로드해서 사용할 수 있도록 되어 있습니다.  그리고 다양한 OS에 포팅되어 있어서 리눅스는 물론이고 OSX까지 포팅되어 있습니다. MIPS 어셈블러를 테스트 해보고 싶은 분들에게는 좋은 출발점이 될 수 있는 프로그램입니다.

창을 열면 위와 같이 GUI창이 나오는데 마치 DDD를 보는 것 같은 느낌입니다.
용법은 대개 쉬워서 가운데 부분에 있는 버튼들을 잘 두들기면 됩니다.

실행 방법
  xspim assembler_file_name
입니다.

  예를 들어서 tt.endians.s 라는 어셈블러 파일을 실행하고 싶으면 다음과 같이 합니다.

  xspim tt.endians.s

그러면 다음과 같이 창이 나타납니다.
사용자 삽입 이미지
Step 커맨드 버튼을 눌르면 한 스텝씩 진행됩니다.
몇가지 System Function을 지원하는데 그중에 하나가 print문입니다.

tt.endians.s 파일은 아래와 같습니다.

......
        .data
saved_ret_pc:   .word 0         # Holds PC to return from main
m3:     .asciiz "The next few lines should contain exception error messages\n"
m4:     .asciiz "Done with exceptions\n\n"
m5:     .asciiz "Expect an address error exception:\n   "
m6:     .asciiz "Expect two address error exceptions:\n"
        .text
        .globl main
main:
        sw $31 saved_ret_pc

        .data
lb_:    .asciiz "Testing LB\n"
lbd_:   .byte 1, -1, 0, 128
lbd1_:  .word 0x76543210, 0xfedcba98
        .text
        li $v0 4        # syscall 4 (print_str)  <--
        la $a0 lb_
        syscall

        la $2 lbd_
        lb $3 0($2)
        bne $3 1 fail
        lb $3 1($2)
        bne $3 -1 fail
        lb $3 2($2)
        bne $3 0 fail
        lb $3 3($2)
        bne $3 0xffffff80 fail
.......
 
위에서 보는 것 처럼 $v0에 4를 넣고 (print str system call 번호입니다.)
$a0에 해당 스트링의 어드레스를 넣은 뒤에 syscall을 수행하면 위의 그림처럼 메시지가 출력됩니다.

디버깅시에 편한 용법입니다.

디버깅 창의 제일 밑에보면 수행되는 명령어 시퀀스를 하나씩 출력합니다.

SPIM Version 8.0 of January 8, 2010
Copyright 1990-2010, James R. Larus.
All Rights Reserved.
See the file README for a full copyright notice.
Loaded: /usr/local/lib/spim/exceptions.s
[0x00400000] 0x8fa40000  lw $4, 0($29)                   ; 183: lw $a0 0($sp) # argc
[0x00400004] 0x27a50004  addiu $5, $29, 4                ; 184: addiu $a1 $sp 4 # argv
[0x00400008] 0x24a60004  addiu $6, $5, 4                 ; 185: addiu $a2 $a1 4 # envp
[0x0040000c] 0x00041080  sll $2, $4, 2                   ; 186: sll $v0 $a0 2
[0x00400010] 0x00c23021  addu $6, $6, $2                 ; 187: addu $a2 $a2 $v0
[0x00400014] 0x0c100009  jal 0x00400024 [main]           ; 188: jal main <--
[0x00400024] 0x3c011001  lui $1, 4097                    ; 45: sw $31 saved_ret_pc
[0x00400028] 0xac3f0000  sw $31, 0($1)
[0x0040002c] 0x34020004  ori $2, $0, 4                   ; 52: li $v0 4 # syscall 4 (print_str)
[0x00400030] 0x3c011001  lui $1, 4097 [lb_]              ; 53: la $a0 lb_
[0x00400034] 0x342400a2  ori $4, $1, 162 [lb_]
[0x00400038] 0x0000000c  syscall                         ; 54: syscall
[0x0040003c] 0x3c011001  lui $1, 4097 [lbd_]             ; 56: la $2 lbd_
[0x00400040] 0x342200ae  ori $2, $1, 174 [lbd_]
[0x00400044] 0x80430000  lb $3, 0($2)                    ; 57: lb $3 0($2)
[0x00400048] 0x34010001  ori $1, $0, 1                   ; 58: bne $3 1 fail
[0x0040004c] 0x14230243  bne $1, $3, 2316 [fail-0x0040004c]
[0x00400050] 0x80430001  lb $3, 1($2)                    ; 59: lb $3 1($2)
[0x00400054] 0x3c01ffff  lui $1, -1                      ; 60: bne $3 -1 fail


00400014 에서 JAL을 하므로 00400024로 점프합니다. 이것은 main에 해당되는 어드레스입니다.
따라서 System Reset시에는 00400000부터 시작함을 알 수 있습니다.

해당되는 코드는

./CPU/exception.S

파일에 있습니다.  해당 파일을 보면

.......
# Standard startup code.  Invoke the routine "main" with arguments:
#       main(argc, argv, envp)
#
        .text
        .globl __start
__start:
        lw $a0 0($sp)           # argc
        addiu $a1 $sp 4         # argv
        addiu $a2 $a1 4         # envp
        sll $v0 $a0 2
        addu $a2 $a2 $v0
        jal main  <--
        nop

        li $v0 10
        syscall                 # syscall 10 (exit)

        .globl __eoth
__eoth:
.......

으로 되어 있어서 _start부터 리셋 스타트가 시작되고 있음을 알 수 있습니다.
여기서 jal main을 수행하므로 여기서 유저가 짠 프로그램으로 점프 하고 있습니다.

'ASIC SoC' 카테고리의 다른 글

EMACS에 Verilog Mode 설치하고 활용하기  (2) 2010.10.30
사상 최강의 보드  (2) 2010.04.18
HD Quad Display/Processing Engine  (1) 2010.03.12
Sound Effect Processor  (0) 2010.02.01
[SC] Structure  (0) 2010.01.18
Posted by GUNDAM_IM
ASIC SoC2010. 3. 12. 06:47

HD Quad Processing Engine을 개발


HD 화면을 4개를 받아서 하나의 화면으로 자유롭게 스케일링하고, Overlay를 하여서 Display할 수 있는 엔진입니다. HD급 대역폭 4개를 동시에 처리해야 하기 때문에 Traffic 처리 부분과 이미지 처리 부분에 대해서 많은 기능이 들어간 엔진입니다.

사용자 삽입 이미지

력 및 출력은

   3G-SDI, HD-SDI, DVI, HDMI 등을 지원 하며
   1920x1080 까지 지원이 됩니다.
   SMPTE 표준안을 지원하고 있습니다.

내부에

    Free Size Image Scaler와 Image Enhancer를 내장하고 있어서 화면 구성을 자유롭게 할 수 있음.
    관심 영역에 대한 CROP기능을 지원

Image Layer는 8개를 지원

   
사용자 삽입 이미지
   
   Overlay, Quad Layer , OSG, Cascade 등 모두 8개 Layer를 지원합니다.
   Quad Layer는 이미지 별로 레이어를 설정할 수 있도록 되어 있습니다.


    
사용자 삽입 이미지

Cascade Display


 복수개의 화면을 구성한다면 그만큼 엔진을 연결하면 됩니다.
 예를 들어서 16개의 HD화면을 구성한다면 4개의 엔진을 붙이면 화면 구성이 자유롭게 16개까지 구성 가능합니다. 필요하다면 16개의 엔진을 구성한다면 16*4 = 64개의 HD 화면을 처리할 수 있습니다.

최종 보드

  이 엔진을 이용하여 구성한 보드의 사진입니다.
사용자 삽입 이미지

첨부하는 파일은 제품 관련 브로셔입니다.
관련 홈페이지는 이곳을 참조하여주세요

www.silicongear.co.kr


(음 자료를 자꾸 업데이트 하다 보니까 완전히 회사 광고가 되어버렸네요)

'ASIC SoC' 카테고리의 다른 글

사상 최강의 보드  (2) 2010.04.18
[MIPS] MIPS assembler simulator XSPIM  (8) 2010.03.21
Sound Effect Processor  (0) 2010.02.01
[SC] Structure  (0) 2010.01.18
[MIPS] OSX에서 MIPS C Compiler를 빌드하기  (0) 2009.12.17
Posted by GUNDAM_IM
ASIC SoC2010. 2. 1. 15:51

사용자 삽입 이미지

예전에 글로 올렸던 사운드 프로세싱 프로세서입니다.

내부에 강력한 Engine이 들어있어서 다양한 음향효과를 지원할 수 있습니다.

드디어 양산에 들어갔네요


 기술개요


 자체 개발한 고성능 사운드 이펙트 엔진과 ARM926프로세서를 내장한 칩셋


 제품특징


 음향 및 사운드 처리를 위한 고성능 프로세싱 엔진과 다양한 Sample Rate를 지원하기 위한

 Audio Sample Rate Converter Engine을 내장


 사운드 이펙트 엔진은 내부에 고성능의 DSP를 내장하여, 어플리케이션에 따라서 다양한 처리 가능


외부 시스템 인터페이스를 위하여 I2S 및 SPDIF 기능을 가지고 있어 다양한 오디오/사운드 어플리케이션을 지원

 시스템 인터페이스를 위해서 UART, I2C 등이 내장


사용자 삽입 이미지

관련 글은 요기 참조


'ASIC SoC' 카테고리의 다른 글

[MIPS] MIPS assembler simulator XSPIM  (8) 2010.03.21
HD Quad Display/Processing Engine  (1) 2010.03.12
[SC] Structure  (0) 2010.01.18
[MIPS] OSX에서 MIPS C Compiler를 빌드하기  (0) 2009.12.17
PERL TIP  (0) 2009.12.05
Posted by GUNDAM_IM
ASIC SoC2010. 1. 18. 17:04
SystemC로 설계하는 도중에 정리를 하지 못한것이 있었습니다.
- 이 문제로 반나절을 버그 찾느라고 날렸습니다.
- 알고나면 아주 간단한건데 역시 모르면 닭질하는군요

이 내용는 KAP의  SystemC: from the ground up에서 가지고 왔습니다.
Chapter 10절에 해당하는 내용입니다.

계층적으로 설계할 경우 서브 모듈에서 다른 서브 모듈을 불러서 할 경우 2가지 방법이 있습니다.
하나는 Direct sub module header only implementation 방식이고
다른 하나는 Indirect sub module header only implementation 방식입니다.

아래와 같은 방식이 전자인 직접 연결 방식입니다.

SC_MODULE(body)
{
.......
   Wheel wheel_R ;
   Wheel wheel_L ;
........

  CTOR(body)
    : wheel_R("WHEEL_R"),
      wheel_L("WHEEL_L")
    {
      ......

      ......
    }


};

아래 방식이 간접 연결 방식입니다.

SC_MODULE(body)
{
.......
   Wheel pWheel_R ;
   Wheel pWheel_L ;
........

  CTOR(body)
    {
      ......
     pWheel_R = new Wheel("Wheel_R");
     pWheel_L = new Wheel("Wheel_L");
      ......
    }
 ...
};


차이점은 직접 인스턴스를 만드느냐 아니면 포인터로 받느냐 입니다.
에궁 이 단순한것도 몰라서 고생하다니 웬지 억울합니다.
매뉴얼 안보고 게임하는거나 같군요

'ASIC SoC' 카테고리의 다른 글

HD Quad Display/Processing Engine  (1) 2010.03.12
Sound Effect Processor  (0) 2010.02.01
[MIPS] OSX에서 MIPS C Compiler를 빌드하기  (0) 2009.12.17
PERL TIP  (0) 2009.12.05
Timing Chart  (0) 2009.11.08
Posted by GUNDAM_IM