電気回路/HDL/SystemC の導入

(462d) 更新


公開メモ

Verilator で SystemC によるテストベンチを動かす

Verilator を使うと Verilog モジュールを SystemC に変換し、 同じく SystemC で書いたテストベンチを用いて検証することが可能、 とのことでやってみました。

Verilator のインストール方法は 電気回路/HDL/Verilator の導入(C++モード) にあります。

また、続きとして Verilator でカバレッジ測定を行ってみた結果を 電気回路/HDL/SystemPerl の導入 にまとめました。

加えて、SystemC について多少勉強した結果を 電気回路/HDL/SystemC によるテストベンチ にまとめつつあります。

SystemC のインストール

SystemC の実体は C++ 上のクラスライブラリです。

Verilator を使うと合成可能な Verilog モジュール(テストベンチではない)を SystemC ライブラリ互換のコードに変換することができます。 そのコードをコンパイルするには SystemC のインクルードファイルが必要となり、 また、実行形式を作成するには SystemC のライブラリとリンクする必要があります。

ということで、SystemC のインストールを行うことにしました。

SystemC は http://www.systemc.org/downloads/lrm から無償で落とせるのですが、 簡単なユーザー登録が必要でした。

いろいろ落としてきましたが、ここではライブラリの本体である systemc-2.2.0 のみをインストールします。

LANG:console
$ cd systemc/

$ ls
 OSCI_SystemC_AMS_extensions_1v0_Standard.zip*  scv-1.0p2-sysc2.2.12jun06.tgz*
 TLM-2.0.1.tgz*                                 systemc-2.2.0.tgz*
 TLM_2_0_LRM.pdf*                               systemc_tests-2.2.0.tgz*
 
$ tar fxz systemc-2.2.0.tgz

$ ls
 OSCI_SystemC_AMS_extensions_1v0_Standard.zip*  systemc-2.2.0/
 TLM-2.0.1.tgz                                 systemc-2.2.0.tgz
 TLM_2_0_LRM.pdf                              systemc_tests-2.2.0.tgz
 scv-1.0p2-sysc2.2.12jun06.tgz

$ cd systemc-2.2.0/

$ ls
 AUTHORS    LICENSE      README        configure*    msvc60/
 COPYING    Makefile.am  RELEASENOTES  configure.in  msvc71/
 ChangeLog  Makefile.in  aclocal.m4    docs/         src/
 INSTALL    NEWS         config/       examples/

$ less INSTALL
 Basic SystemC Installation
 ==========================
 
 To install SystemC on a UNIX system, do the following steps:
 
   1. Change to the top level directory (systemc-2.2)
 
   2. Create a temporary directory, e.g.,
 
         > mkdir objdir
 
   3. Change to the temporary directory, e.g.,
 
         > cd objdir
 
   4. Set the following environment variable(s):
 
      For gcc compilers on Linux:
 
         > setenv CXX g++
 
      You can also specify an absolute path to the compiler of your choice.
 
   5. Configure the package for your system, e.g.,
      (The configure script is explained below.)
 
         > ../configure
 
      While the 'configure' script is running, which takes a few moments,
      it prints messages to inform you of the features it is checking.
      It also detects the platform.
 
      SystemC 2.2 includes a fixed-point package that is always built.
      When compiling your applications with fixed-point types, you still have
      to use compiler flag -DSC_INCLUDE_FX. Note that compile times increase
      significantly when using this compiler flag.
 
      In case you want to install the package in another place than the
      top level directory (systemc-2.2), configure the package e.g. as
      follows:
 
         > ../configure --prefix=/usr/local/systemc-2.2
 
      Note: make sure you have created the target directory before installing
            the package. Do _not_ use /usr/local as a prefix.
 
   6. Compile the package.
 
      For an optimized SystemC library, enter:
 
         > gmake
 
      For a debug SystemC library, enter:
 
         > gmake debug
 
   7. Install the package.
 
         > gmake install
 
   8. At this point you may wish to verify the installation by
      testing the example suite.
 
         > gmake check
 
      this will compile and run the examples in the subdirectory
      examples.
 
   9. You can now remove the temporary directory, .e.g,
 
         > cd ..
         > rm -rf objdir
 
      Alternatively, you can keep the temporary directory to allow
      you to:
 
      a) Experiment with the examples.
 
      b) Later uninstall the package. To clean up the temporary
         directory, enter:
 
             > gmake clean
 
         To uninstall the package, enter:
 
             > gmake uninstall
 
 
 Running the Examples
 ====================
 
 A copy of the examples reside in the temporary directory - see
 instruction 8 above for details on building and running them.
 
 In addition, a copy of the example code resides in the directory
 examples at the highest level of the installation.
 
 Use the makefiles provided in  the 'examples' directory as templates
 for makefiles you need for compiling your own examples.
 
$ mkdir objdir

$ cd objdir/

$ g++ --version
 g++ (GCC) 4.3.4 20090804 (release) 1
 Copyright (C) 2008 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ export CXX=g++

$ ../configure
checking build system type... i686-pc-cygwin
checking host system type... i686-pc-cygwin
checking target system type... i686-pc-cygwin
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
/home/osamu/systemc/systemc-2.2.0/config/missing: Unknown `--run' option
Try `/home/osamu/systemc/systemc-2.2.0/config/missing --help' for more informati
on
configure: WARNING: `missing' script is too old or missing
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.exe
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... .exe
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking dependency style of g++... gcc3
checking for ranlib... ranlib
checking for a BSD-compatible install... /usr/bin/install -c
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating src/sysc/Makefile
config.status: creating src/sysc/communication/Makefile
config.status: creating src/sysc/datatypes/Makefile
config.status: creating src/sysc/datatypes/bit/Makefile
config.status: creating src/sysc/datatypes/fx/Makefile
config.status: creating src/sysc/datatypes/int/Makefile
config.status: creating src/sysc/datatypes/misc/Makefile
config.status: creating src/sysc/kernel/Makefile
config.status: creating src/sysc/tracing/Makefile
config.status: creating src/sysc/qt/Makefile
config.status: creating src/sysc/utils/Makefile
config.status: creating src/sysc/packages/Makefile
config.status: creating src/sysc/packages/boost/Makefile
config.status: creating src/sysc/packages/boost/bind/Makefile
config.status: creating src/sysc/packages/boost/config/Makefile
config.status: creating src/sysc/packages/boost/config/compiler/Makefile
config.status: creating src/sysc/packages/boost/config/platform/Makefile
config.status: creating src/sysc/packages/boost/config/stdlib/Makefile
config.status: creating src/sysc/packages/boost/mpl/Makefile
config.status: creating src/sysc/packages/boost/mpl/aux_/Makefile
config.status: creating src/sysc/packages/boost/mpl/aux_/config/Makefile
config.status: creating src/sysc/packages/boost/detail/Makefile
config.status: creating src/sysc/packages/boost/utility/Makefile
config.status: creating src/sysc/packages/boost/utility/detail/Makefile
config.status: creating examples/Makefile
config.status: creating examples/sysc/Makefile
config.status: creating examples/sysc/fir/Makefile
config.status: creating examples/sysc/fft/Makefile
config.status: creating examples/sysc/fft/fft_flpt/Makefile
config.status: creating examples/sysc/fft/fft_fxpt/Makefile
config.status: creating examples/sysc/pipe/Makefile
config.status: creating examples/sysc/pkt_switch/Makefile
config.status: creating examples/sysc/rsa/Makefile
config.status: creating examples/sysc/simple_bus/Makefile
config.status: creating examples/sysc/simple_fifo/Makefile
config.status: creating examples/sysc/simple_perf/Makefile
config.status: creating examples/sysc/2.1/Makefile
config.status: creating examples/sysc/2.1/dpipe/Makefile
config.status: creating examples/sysc/2.1/forkjoin/Makefile
config.status: creating examples/sysc/2.1/reset_signal_is/Makefile
config.status: creating examples/sysc/2.1/sc_export/Makefile
config.status: creating examples/sysc/2.1/sc_report/Makefile
config.status: creating examples/sysc/2.1/scx_barrier/Makefile
config.status: creating examples/sysc/2.1/scx_mutex_w_policy/Makefile
config.status: creating examples/sysc/2.1/specialized_signals/Makefile
config.status: executing depfiles commands

$ make
 ...

 g++ -I. -I. -I../../../../src/sysc/utils -I../../../../src    -Wall -DSC_INCLUDE
 _FX -O3 -c -o sc_utils_ids.o `test -f '../../../../src/sysc/utils/sc_utils_ids.c
 pp' || echo '../../../../src/sysc/utils/'`../../../../src/sysc/utils/sc_utils_id
 s.cpp
 ../../../../src/sysc/utils/sc_utils_ids.cpp: In function ‘int sc_core::initiali
 ze()’:
 ../../../../src/sysc/utils/sc_utils_ids.cpp:110: error: ‘getenv’ is not a memb
 er of ‘std’
 ../../../../src/sysc/utils/sc_utils_ids.cpp:111: error: ‘strcmp’ was not decla
 red in this scope
 ../../../../src/sysc/utils/sc_utils_ids.cpp: At global scope:
 ../../../../src/sysc/utils/sc_utils_ids.cpp:119: warning: ‘sc_core::forty_two’
  defined but not used
 make[3]: *** [sc_utils_ids.o] Error 1
 make[3]: Leaving directory `/home/osamu/systemc/systemc-2.2.0/objdir/src/sysc/ut
 ils'
 make[2]: *** [all-recursive] Error 1
 make[2]: Leaving directory `/home/osamu/systemc/systemc-2.2.0/objdir/src/sysc'
 make[1]: *** [all-recursive] Error 1
 make[1]: Leaving directory `/home/osamu/systemc/systemc-2.2.0/objdir/src'
 make: *** [all-recursive] Error 1

エラー出ました。

LANG:console
 ../../../../src/sysc/utils/sc_utils_ids.cpp
 110: error: ‘getenv’ is not a member of ‘std’
 111: error: ‘strcmp’ was not declared in this scope

雰囲気からすると #include のし忘れなんですが・・・ まさか配布されてるソースでそれはないですよね???

と思ったら、http://www10.atwiki.jp/bambooflow/pages/77.html そのまんま、ですか?!

../src/sysc/utils/sc_utils_ids.cpp の先頭に

LANG:CPP
#include "string.h"
#include "cstdlib"

を追加したらエラーがなくなりました。

LANG:console
$ make
 ...

$ make install
 ...

インストール終了。

正しくインストールされたかをチェックする

INSTALL の指示通りに続けます。

LANG:console
$ make check
 ...
 make[5]: Entering directory `/home/osamu/systemc/systemc-2.2.0/objdir/examples/s
 ysc/fft/fft_flpt'
 
              SystemC 2.2.0 --- Oct 29 2010 15:07:40
         Copyright (c) 1996-2006 by all Contributors
                     ALL RIGHTS RESERVED
 assertion "m_stack_size > ( 2 * pagesize )" failed: file "../../../../src/sysc/k
 ernel/sc_cor_qt.cpp", line 93, function: virtual void sc_core::sc_cor_qt::stack_
 protect(bool)
 /bin/sh: line 4:  6600 Aborted                 (core dumped) ${dir}$tst
 FAIL: fft.exe
 ===================
 1 of 1 tests failed
 ===================

エラー出ました。

http://verificationguild.com/modules.php?name=Forums&file=viewtopic&t=1501&view=previous

によると、スタックサイズが小さすぎてオーバーフローしているそうです。

で、なぜだか make 時に pthreads を付けて POSIX threads バージョンを使えば問題は解決するはず、と。

スレッドに分けると1スレッドあたりの消費スタック数が減るということですかね???

LANG:console
$ make clean
 ...

$ make pthreads
 ...

$ make install
 ...

$ make check
 ...

 make[5]: Entering directory `/home/osamu/systemc/systemc-2.2.0/objdir/examples/s
 ysc/fft/fft_flpt'
 
              SystemC 2.2.0 --- Oct 29 2010 15:07:40
         Copyright (c) 1996-2006 by all Contributors
                     ALL RIGHTS RESERVED
 assertion "m_stack_size > ( 2 * pagesize )" failed: file "../../../../src/sysc/k
 ernel/sc_cor_qt.cpp", line 93, function: virtual void sc_core::sc_cor_qt::stack_
 protect(bool)
 /bin/sh: line 4:  7992 Aborted                 (core dumped) ${dir}$tst
 FAIL: fft.exe
 ===================
 1 of 1 tests failed
 ===================

やっぱりエラー出ました(汗

あら、http://www10.atwiki.jp/bambooflow/pages/77.html にちゃんと書いてありました。

もう一方の解法として挙げられていた、スタックサイズの調整も必要なようです。

いじるのは、
include/sysc/kernel/sc_constants.h

で、

LANG:CPP
const int SC_DEFAULT_STACK_SIZE   = 0x10000;

LANG:CPP
const int SC_DEFAULT_STACK_SIZE   = 0x50000;

としました。

さらに、上記 URL で指示されているとおり make pthreads_check もやってみました。

LANG:console
$ make clean
 ...

$ make pthreads
 ...

$ make install
 ...

$ make check
 ...

$ make pthreads_check
 ...

特に初回の make check にかなりの時間がかかるので、 その間に http://homepage3.nifty.com/hdl_design/systemc.htm でお勉強。

途中でキー入力を求めるテストもあって、 ちょっとどうかな、とも思いますが、 エラー無く通りました。

これで SystemC ライブラリが ~/systemc/systemc-2.2.0/ にできあがりました。

SystemC を使って Verilator テスト

http://www10.atwiki.jp/bambooflow/pages/53.html

http://www.applistar.com/technologies/

http://homepage3.nifty.com/hdl_design/systemc.htm

あたりをちらちら見てみましたが、細かい文法はともかく、 まずはテストベンチを動かしてみたい。

そこで、最低限の約束事だけ頭に入れ、簡単なテストベンチを作り、 Verilator 変換した verilog モジュールとともに動かしてみました。

流れ的には 電気回路/HDL/Verilator の導入(C++モード) の続きになります。

bin2bcd_sc.cpp

LANG:cpp(linenumber)
#include "Vbin2bcd.h"
int sc_main(int argc, char **argv) {

    Verilated::commandArgs(argc, argv);

    sc_clock clk ("clk", 10);
    sc_signal<bool> rst, start, busy;
    sc_signal<uint32_t> bin;
    sc_signal<uint32_t> bcd;

    Vbin2bcd top("top");
    top.clk(clk);

    top.rst(rst);
    top.start(start);
    top.busy(busy);
    top.bin(bin);
    top.bcd(bcd);

    // 検証開始
    rst = 1;
    start = 0;
    bin = 123;

    sc_start(100, SC_NS);
    rst = 0;

    sc_start(100, SC_NS);
    start = 1;
    
    sc_start(10, SC_NS);
    start = 0;
    
    sc_start(10, SC_NS);
    while(busy)
        sc_start(10, SC_NS);

    cout << hex << showbase << bcd << endl;

    exit(0);
}

を用意して、

LANG:console
$ rm obj_dir/*

$ verilator -sc -Wno-lint bin2bcd.v --exe bin2bcd_sc.cpp
 %Error: Need $SYSTEMC in environment
 Probably System-C isn't installed, see http://www.systemc.org
 %Error: Command Failed verilator_bin -sc -Wno-lint bin2bcd.
 v --exe bin2bcd_sc.cpp

$ export SYSTEMC=~/systemc/systemc-2.2.0/

$ verilator -sc -Wno-lint bin2bcd.v --exe bin2bcd_sc.cpp

$ cd obj_dir

$ make -j -f Vbin2bcd.mk Vbin2bcd
 g++  -I. -MMD -I/home/osamu/verilator-3.804/include -I/home/osamu/verilator-3.80
  4/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -I/home/
  osamu/systemc/systemc-2.2.0//include  -c -o bin2bcd_sc.o ../bin2bcd_sc.cpp
 g++     -L/home/osamu/systemc/systemc-2.2.0//lib-cygwin bin2bcd_sc.o verilated.o
  Vbin2bcd__ALL.a    -o Vbin2bcd -lm -lstdc++ -lsystemc 2>&1 | c++filt

$ ls
 Vbin2bcd.cpp          Vbin2bcd__ALLcls.o    Vbin2bcd__verFiles.dat
 Vbin2bcd.exe*         Vbin2bcd__ALLsup.cpp  Vbin2bcd_classes.mk
 Vbin2bcd.h            Vbin2bcd__ALLsup.d    bin2bcd_sc.d
 Vbin2bcd.mk           Vbin2bcd__ALLsup.o    bin2bcd_sc.o
 Vbin2bcd__ALL.a       Vbin2bcd__Syms.cpp    verilated.d
 Vbin2bcd__ALLcls.cpp  Vbin2bcd__Syms.h      verilated.o
 Vbin2bcd__ALLcls.d    Vbin2bcd__ver.d
 
$ ./Vbin2bcd.exe
 
              SystemC 2.2.0 --- Oct 29 2010 15:47:29
         Copyright (c) 1996-2006 by all Contributors
                     ALL RIGHTS RESERVED
 
 Info: (I804) /IEEE_Std_1666/deprecated:
     sc_clock(const char*, double, double, double, bool)
     is deprecated use a form that includes sc_time or
     sc_time_unit
 0x123

ということで、ちゃんと動いているようです。

SystemC の良いところは、テストベンチ中で C++ の機能を 100% 生かせることなので、 テスト部分を少し変更して、以下のようにしてみました。

LANG:cpp(linenumber)
#include "Vbin2bcd.h"
int sc_main(int argc, char **argv) {

    Verilated::commandArgs(argc, argv);

    sc_clock            clk ("clk", 10, SC_NS);
    sc_signal<bool>     rst, start, busy;
    sc_signal<uint32_t> bin;
    sc_signal<uint32_t> bcd;

    Vbin2bcd top("top");

    top.clk(clk);
    top.rst(rst);
    top.start(start);
    top.busy(busy);
    top.bin(bin);
    top.bcd(bcd);

    // 検証開始
    rst   = 1;
    start = 0;

    sc_start(100, SC_NS);
    rst = 0;
    sc_start(100, SC_NS);

    for(int i=0; i<1024; i++) {
        
        bin = i;

        start = 1;
        sc_start(10, SC_NS);
        start = 0;
        
        sc_start(10, SC_NS);
        while(busy)
            sc_start(10, SC_NS);

        std::ostringstream os_bin;
        std::ostringstream os_dec;
        
        os_bin << dec << i;     // 元の数値を10進数で表したもの
        os_dec << hex << bcd;   // 変換結果を16進数で表したもの
        sc_assert(os_bin.str()==os_dec.str()); // 等しいことを検証
        
        sc_start(40, SC_NS);
    }
    
    cout << "done";

    exit(0);
}

同時に、clk の指定も上記 warning を元に直してあります。

LANG:console
$ make -j -f Vbin2bcd.mk Vbin2bcd
 g++  -I. -MMD -I/home/osamu/verilator-3.804/include -I/home/osamu/verilator-3.80
  4/include/vltstd -DVL_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0        -I/home/
  osamu/systemc/systemc-2.2.0//include  -c -o bin2bcd_sc.o ../bin2bcd_sc.cpp
 g++     -L/home/osamu/systemc/systemc-2.2.0//lib-cygwin bin2bcd_sc.o verilated.o
  Vbin2bcd__ALL.a    -o Vbin2bcd -lm -lstdc++ -lsystemc 2>&1 | c++filt

$ ./Vbin2bcd.exe
 
              SystemC 2.2.0 --- Oct 29 2010 15:47:29
         Copyright (c) 1996-2006 by all Contributors
                     ALL RIGHTS RESERVED
 done

うん、これはいいかも。

verilog モジュールのテストを SystemC で書ければ、 SystemVerilog + DPI-C でやっていたようなことを もっと簡単にできるのかも?
>> 電気回路/HDL/ModelSim XE を使った SystemVerilog DPI-C テスト

verilog では @(posedge clk); というような書き方で クロックエッジや任意信号の立ち上がり・立ち下がりを待つ 遅延をテストベンチの任意箇所に書くことができたのですが、 SystemC ではそういう遅延を書くやり方は無いみたいですかね?

まだまだ勉強が必要そうです。

こちらのサイトは例示が具体的で勉強になりますね。
http://systemcjapan.com/systemc_lang/systemc_introduction1.html

多少勉強しつつある結果> 電気回路/HDL/SystemC によるテストベンチ

また、続きとして Verilator でカバレッジ測定を行ってみた結果を 電気回路/HDL/SystemPerl の導入 にまとめました。

関連記事

コメント





Counter: 27755 (from 2010/06/03), today: 4, yesterday: 0