電気回路/HDL/SystemC の導入 の履歴(No.2)
更新Verilator で SystemC によるテストベンチを動かす†
Verilator を使えば Verilog モジュールを SystemC のテストベンチで検証することが可能とのことで、 やってみました。
さらに、カバレッジ測定を行ってみた結果を 電気回路/HDL/SystemPerl の導入 にまとめました。
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
によると、スタックサイズが小さすぎてオーバーフローしているそうです。
で、なぜだか 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 を使って Verilator テスト†
http://www10.atwiki.jp/bambooflow/pages/53.html
http://www.applistar.com/technologies/
http://homepage3.nifty.com/hdl_design/systemc.htm
あたりをちらちら見てみましたが、細かい文法はともかく、 まずはテストベンチをかしてみたい。
そこで、最低限の約束事だけ頭に入れて、 Verilator を使い、簡単なテストベンチを作って動かしてみました。
流れ的には 電気回路/HDL/Verilator の導入(C++モード) の続きになります。
bin2bcd_sc.cpp
LANG:cpp #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<uint64_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 らしさを生かすつもりで、テスト部分をちょっと変更。
LANG:cpp #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<uint64_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 でやっていたようなことを もっと簡単にできるのかも?
verilog では @(posedge clk); というような書き方で クロックエッジや任意信号の立ち上がり・立ち下がりを待つ 遅延をテストベンチの任意箇所に書くことができたのですが、 SystemC でそういう遅延を書くやり方は無いんでしょうか?
まだまだ勉強が必要そうです。
こちらのサイトは例示が具体的で勉強になりますね。
http://systemcjapan.com/systemc_lang/systemc_introduction1.html
さらに、カバレッジ測定を行ってみた結果を 電気回路/HDL/SystemPerl の導入 にまとめました。
ソースを変更したせいで†
ただ、カバレッジ計測のためにテストベンチのソースをいじらなければならないのは感心しないところです。
上記ソースのまま、--coverage を付けず -sc でコンパイルしようとすると、
LANG:console $ cd .. $ rm -r obj_dir/ $ 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.804/include/vltstd -DV L_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++ -I. -MMD -I/home/osamu/verilator-3.804/include -I/home/osamu/verilator-3.804/include/vltstd -DV L_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -I/home/osamu/systemc/systemc-2.2.0//include -c -o verilated.o /home/osamu/verilator-3.804/include/verilated.cpp /usr/bin/perl /home/osamu/verilator-3.804/bin/verilator_includer Vbin2bcd.cpp > Vbin2bcd__ALLcls.cpp /usr/bin/perl /home/osamu/verilator-3.804/bin/verilator_includer Vbin2bcd__Syms.cpp > Vbin2bcd__ALLs up.cpp g++ -I. -MMD -I/home/osamu/verilator-3.804/include -I/home/osamu/verilator-3.804/include/vltstd -DV L_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -I/home/osamu/systemc/systemc-2.2.0//include -c -o Vbin2bcd__ALLsup.o Vbin2bcd__ALLsup.cpp g++ -I. -MMD -I/home/osamu/verilator-3.804/include -I/home/osamu/verilator-3.804/include/vltstd -DV L_PRINTF=printf -DVM_TRACE=0 -DVM_COVERAGE=0 -I/home/osamu/systemc/systemc-2.2.0//include -c -o Vbin2bcd__ALLcls.o Vbin2bcd__ALLcls.cpp ../bin2bcd_sc.cpp: In function ‘int sc_main(int, char**)’: ../bin2bcd_sc.cpp:60: error: ‘SpCoverage’ has not been declared make: *** [bin2bcd_sc.o] Error 1 make: *** Waiting for unfinished jobs....
となって止まってしまいます。
#ifdef SYSTEMPERL で囲っても駄目なのはあたりまえなので、
--coverage を付けた時だけ有効になるような定義済みマクロがないか探しているところです。