日曜技術者のメモ

趣味でやった事のメモ書きです。

C++11とC++14とSystemC

C++11やC++14といった新しいC++でSystemCを使ったらどうなるか軽く試したメモ

C++11

C++11でSystemCがどうなるかについては↓の資料にまとめられています。

http://www.nascug.org/events/17th/black_cpp11_2_27_2012.pdf

一番気になったのはテンプレートについて。
C99だと>が二つ続く際は右シフトと認識しない様にスペースが必要。 でもC++11ではちゃんと判別してくれる様です。

実際にやってみた。

#include <systemc.h>

int sc_main(int argc, char *argv[]) {
    
    sc_signal<sc_uint<5> > c99;
    sc_signal<sc_uint<5>>  cpp11;  //こっちはC++11専用

}

C99環境だと

clang++ -O2 -Wall -I. -I/home/ginnyu-tei/lib/SystemC-2.3.0_Debug//include -c main.cpp
main.cpp:6:25: error: use of undeclared identifier 'cpp11'
        sc_signal<sc_uint<5>>  cpp11; 
                               ^
main.cpp:6:30: error: expected a type
        sc_signal<sc_uint<5>>  cpp11; 
                                    ^
2 errors generated.
make: *** [main.o] エラー 1

もちろんエラー
次は同じコードをC++11環境でやってみる。
C++11環境にするにはオプションに-std=c++11を追加する。
(gccのバージョンによっては-std=c++0x)

clang++ -O2 -Wall -std=c++11 -I. -I/home/ginnyu-tei/lib/SystemC-2.3.0_Debug//include -c main.cpp
clang++ -o run.x -L. -L/home/ginnyu-tei/lib/SystemC-2.3.0_Debug//lib-linux64 -lsystemc -lm  main.o 

問題なくビルド出来ました。

C++14

C++14では2進数表記が追加される様です。
ドラフト規格ですが、コンパイラが独自規格で実装している様なので試してみました。

#include <systemc.h>

int sc_main(int argc, char *argv[]) {

    sc_uint<5> hoge;
    sc_uint<32> piyo;

    hoge = 0b10000;
    piyo = 0b10101010010101010000000011111111;

    cout << std::hex << "hoge = " << hoge << endl;
    cout << std::hex << "piyo = " << piyo << endl;

    return 0;
}

実行結果

[ginnyu-tei@localhost SystemC_Test]$ ./run.x 

             SystemC 2.3.0-ASI --- Mar  9 2014 13:23:24
        Copyright (c) 1996-2012 by all Contributors,
        ALL RIGHTS RESERVED

hoge = 10
piyo = 0aa5500ff

C++14の新機能はまだまだあるけどそれは正式な規格になってから調べる

clangでSystemC2.2をビルドしてみた

clangでSystemC2.2がビルドできたのでメモ
ただしこの方法はclangのバージョン3.3のみに有効

clangインストール

インストールは以下ページを参考にしました。

CentOS5にLLVMとclangをインストールする | CentOS・Red Hat Linux実践テクニック - サンプルコードによるPerl入門 〜 伝統と信頼のPerlを学ぼう 〜

automake-1.6.3 インストール

Fedora Coreに入っているautomakeは1.12は新しすぎて
SystemC2.2では使えないので1.6.3をインストール

wget http://ftp.gnu.org/gnu/automake/automake-1.6.3.tar.gz 
tar zxvf automake-1.6.3.tar.gz
cd automake-1.6.3
./configure
make 
sudo make install

SystemC2.2修正

そのままではビルドできないのでコードに手をいれる。
修正は以下を参照

configure

@@ -3445,7 +3445,7 @@
         ;;
     x86_64*linux*)
         case "$CXX_COMP" in
-            c++ | g++)
+            c++ | g++ | clang++)
                 EXTRA_CXXFLAGS="-Wall"
                 DEBUG_CXXFLAGS="-g"
                 OPT_CXXFLAGS="-O3"

src/sysc/datatypes/bit/sc_bit_proxies.h

@@ -713,7 +713,7 @@
 
 protected:
 
-    mutable X& m_obj;
+    X&         m_obj;
     int        m_hi;
     int        m_lo;
     int        m_len;
@@ -1190,10 +1190,10 @@
 
 protected:
 
-    mutable X&   m_left;
-    mutable Y&   m_right;
+    X&           m_left;
+    Y&           m_right;
     mutable int  m_delete;
-    mutable int& m_refs;
+    int&         m_refs;
 
 private:

src/sysc/datatypes/fx/scfx_rep.h

@@ -74,6 +74,7 @@
 void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int );
 scfx_rep*  neg_scfx_rep( const scfx_rep& );
 scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, int );
+scfx_rep* mult_scfx_rep( const scfx_rep& );
 scfx_rep*  div_scfx_rep( const scfx_rep&, const scfx_rep&, int );
 scfx_rep*  add_scfx_rep( const scfx_rep&, const scfx_rep&, int );
 scfx_rep*  sub_scfx_rep( const scfx_rep&, const scfx_rep&, int );
@@ -374,6 +375,15 @@
 
 inline
 scfx_rep*
+mult_scfx_rep( const scfx_rep& a, const scfx_rep& b)
+{
+    scfx_rep& c = *new scfx_rep;
+    sc_dt::multiply( c, a, b, SC_DEFAULT_MAX_WL_ );
+    return &c;
+}
+
+inline
+scfx_rep*
 lsh_scfx_rep( const scfx_rep& a, int b )
 {
     scfx_rep& c = *new scfx_rep( a );

src/sysc/utils/sc_utils_ids.cpp

@@ -59,6 +59,8 @@
 //
 
 #include "sysc/utils/sc_report.h"
+#include <cstdlib>
+#include <cstring>
 
 
 namespace sc_core {

SystemC2.2ビルド&インストール

手順は普通のやり方。
ただし、環境変数コンパイラをclangにする。

mkdir build
cd build
env CC=clang CXX=clang++ ../configure --prefix=/home/ginnyu-tei/lib/SystemC-2.2_Clang
make 
sudo make install
make check

参考にしたサイト

LSI設計雑記帳 [SystemC] clangでインストール

clang - Installing SystemC 2.2.0, compilation with GCC 4.6 and package for Fedora - Stack Overflow

GDBでsc_int、sc_uintのアンダー/オーバーフロー検出をしてみた

SystemCライブラリのコードにオーバーフロー/アンダーフローを検出する機構を考えてた時に Twitter上でGDBでできると教えてもらったのでやってみた。

始めはGDB+Pythonを使おうかと思ったけどGDBコマンドでそれっぽくできた。

続きを読む

SystemC+GoogleTestを試してみた

Twitter上でSystemCでテストフレームワークが使えるかの話をしている時に
以下ページを教えてもらったので試してみました。

Using existing unit test frameworks with SystemC - Stack Overflow

ソースコード

まずはページに載っているソースコードをファイルにします。

  • exor2.hxx
  • main.cxx
  • main_1.cxx
  • main_2.cxx
  • stim.hxx
  • mon.hxx

これだけでは足りないので以下サイトに載っているNANDのコードをファイルにする。

Modules and Processes

ファイル名は「nand2.hxx」

googletest

googletestは以下サイトにあるので最新の1.7をダウンロード
解凍後「./configure」「make」

googletest - Google C++ Testing Framework - Google Project Hosting

cmake

googletestはcmakeを使ってビルド環境を作るっぽいのでCMakeLists.txtを作成する。
cmakeを使った事がないので見よう見まねで作成したのが↓

cmake_minimum_required(VERSION 2.6)
project(sc_unit_test)

#SystemC Path
include_directories(/home/ginnyu-tei/work/google_test/_lib/systemc-2.3.0/include)
LINK_DIRECTORIES(/home/ginnyu-tei/work/google_test/_lib/systemc-2.3.0/lib-linux64)

#googletest Path
include_directories(/home/ginnyu-tei/work/google_test/_lib/gtest-1.7.0/include)
LINK_DIRECTORIES(/home/ginnyu-tei/work/google_test/_lib/gtest-1.7.0/lib/.libs)

#main build
add_executable(main main_1.cxx main_2.cxx main.cxx)
target_link_libraries(main pthread systemc gtest)

googletestのライブラリパスは「libgtest.a」があるディレクトリを指定すれば良いですが
ビルド環境によっては「gtest-1.7.0/build」に入っている時があります。

ビルド

ソースコードとCMakeLists.txtを同じフォルダに入れて以下実行

[ginnyu-tei@localhost google_test]$ mkdir build
[ginnyu-tei@localhost google_test]$ cd build/
[ginnyu-tei@localhost build]$ cmake ..
-- The C compiler identification is GNU 4.7.2
-- The CXX compiler identification is GNU 4.7.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ginnyu-tei/work/google_test/build
[ginnyu-tei@localhost build]$ make
Scanning dependencies of target main
[ 33%] Building CXX object CMakeFiles/main.dir/main_1.cxx.o
[ 66%] Building CXX object CMakeFiles/main.dir/main_2.cxx.o
[100%] Building CXX object CMakeFiles/main.dir/main.cxx.o
/home/ginnyu-tei/work/google_test/main.cxx: 関数 ‘int sc_main(int, char**)’ 内:
/home/ginnyu-tei/work/google_test/main.cxx:25:18: 警告: warn_unused_result 属性付きで宣言されている ‘int RUN_ALL_TESTS()’ の戻り値を無視しています [-Wunused-result]
Linking CXX executable main
[100%] Built target main

Warningが出ているがビルドはできた。

実行ログ

[ginnyu-tei@localhost build]$ ./main 

             SystemC 2.3.0-ASI --- Jan  9 2014 22:05:39
        Copyright (c) 1996-2012 by all Contributors,
        ALL RIGHTS RESERVED

Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from systemc_test
[ RUN      ] systemc_test.test1
      Time A B F
       0 s 0 0 0
       0 s 0 0 1
     10 ns 0 1 1
     20 ns 1 0 1
     30 ns 1 1 0

Info: /OSCI/SystemC: Simulation stopped by user.
[       OK ] systemc_test.test1 (1 ms)
[ RUN      ] systemc_test.test2
unknown file: Failure
C++ exception with description "Error: (E113) insert primitive channel failed: elaboration done
In file: sc_prim_channel.cpp:216" thrown in the test body.
[  FAILED  ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (2 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (2 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] systemc_test.test2

 1 FAILED TEST
[       OK ] systemc_test.test2 (2 ms)
[----------] 2 tests from systemc_test (3 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (3 ms total)
[  PASSED  ] 2 tests.
[       OK ] systemc_test.test1 (4 ms)
[ RUN      ] systemc_test.test2
      Time A B F
       0 s 0 0 0
       0 s 0 0 1
     10 ns 0 1 1
     20 ns 1 0 1
     30 ns 1 1 0

Info: /OSCI/SystemC: Simulation stopped by user.
[       OK ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (5 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (5 ms total)
[  PASSED  ] 2 tests.
[       OK ] systemc_test.test2 (2 ms)
[----------] 2 tests from systemc_test (6 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (6 ms total)
[  PASSED  ] 2 tests.
[ginnyu-tei@localhost build]$ 

なんかfailしてる・・・
SystemC2.2に変えてみた。

SystemC2.2で実行する際はmain_1.cxxとmain_2.cxxに以下の
includeを追加しないとエラーになった。 (別の環境では追加しなくてもビルドできたので環境依存かも)

#include <unistd.h>

SC2.3と同じ様にビルドして実行

[ginnyu-tei@localhost build]$ ./main 

             SystemC 2.2.0 --- Jan  9 2014 23:02:22
        Copyright (c) 1996-2006 by all Contributors
                    ALL RIGHTS RESERVED
Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from systemc_test
[ RUN      ] systemc_test.test1
      Time A B F
       0 s 0 0 0
       0 s 0 0 1
     10 ns 0 1 1
     20 ns 1 0 1
     30 ns 1 1 0
SystemC: simulation stopped by user.
[       OK ] systemc_test.test1 (1 ms)
[ RUN      ] systemc_test.test2
unknown file: Failure
C++ exception with description "Error: (E546) sc_start called after sc_stop has been called
In file: sc_simcontext.cpp:1315" thrown in the test body.
[  FAILED  ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (2 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (2 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] systemc_test.test2

 1 FAILED TEST
[       OK ] systemc_test.test2 (2 ms)
[----------] 2 tests from systemc_test (3 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (3 ms total)
[  PASSED  ] 2 tests.
[       OK ] systemc_test.test1 (3 ms)
[ RUN      ] systemc_test.test2
      Time A B F
       0 s 0 0 0
       0 s 0 0 1
     10 ns 0 1 1
     20 ns 1 0 1
     30 ns 1 1 0
SystemC: simulation stopped by user.
[       OK ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (4 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (4 ms total)
[  PASSED  ] 2 tests.
[       OK ] systemc_test.test2 (1 ms)
[----------] 2 tests from systemc_test (5 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (5 ms total)
[  PASSED  ] 2 tests.

うーん・・・分からん・・・

STREAM Benchmarkをやってみた

STREAMというメモリ帯域を測定するベンチマークソフトがあるので試してみました。

http://www.streambench.org/

上記ページにあるFTPサイトにはstream.exeがありますが
Windows32bit版で実行にはCygwin.dllが必要です。

私はWindows7 64bit版なのでソースコードからビルドしました。

ビルドは簡単でstream.cをダウンロードしてMinGWgccでコンパイルするだけです。
(POSIX準拠になっているのでVisualStudioだと存在しないヘッダーがあります。)

以下が実行結果

-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 10000000 (elements), Offset = 0 (elements)
Memory per array = 76.3 MiB (= 0.1 GiB).
Total memory required = 228.9 MiB (= 0.2 GiB).
Each kernel will be executed 10 times.
 The *best* time for each kernel (excluding the first iteration)
 will be used to compute the reported bandwidth.
-------------------------------------------------------------
Your clock granularity/precision appears to be 999 microseconds.
Each test below will take on the order of 24001 microseconds.
   (= 24 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function    Best Rate MB/s  Avg time     Min time     Max time
Copy:            8420.6     0.020112     0.019001     0.021001
Scale:           7999.6     0.020446     0.020001     0.021002
Add:            11428.0     0.021668     0.021001     0.026001
Triad:          10434.4     0.023557     0.023001     0.024002
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-013 on all three arrays
-------------------------------------------------------------

Terasic SoCKitのデモを実行してみた-HPS-

SoCKit System CD(Terasicのページからダウンロード)にデモが入っているので実行してみた。

HPS側は以下デモが入っています。

  • hps_gpio
  • hps_gsensor
  • hps_lcd
  • my_first_hps

デモ実行方法は「My_First_HPS.pdf]に記載されています。

my_first_hps実行方法

  1. C:\altera\13.0sp1\embedded\Embedded_Command_Shell.batを実行 「C:\altera\13.0sp1\embedded」はインストール先とバージョンによって変わるので注意

2.コマンドプロンプトが立ち上がるので「my_first_hps」があるディレクトリまで移動する
 ベースはCygwinなので「cd /cygdrive/<ドライブレター>/」でドライブを移動できる。

3.移動後makeを実行
 コンパイル済みのmy_first_hpsが入っているので一度make cleanした方がコンパイルの様子が見れます。

arm-linux-gnueabihf-gcc -g -Wall  -I C:/altera/13.0sp1/embedded/ip/altera/hps/al
tera_hps/hwlib/include -c main.c -o main.o
arm-linux-gnueabihf-gcc -g -Wall    main.o -o my_first_hps

4.ボードの電源を入れてLinuxを起動しTeraTermを接続する。
 「Terasic SoCKitでLinuxをブートしてみた」と同じ
 LAN経由でプログラムをSoCKitへ転送するので同一ネットワーク内にLANを接続する。

5.SoCKitのipアドレスを確認する
 ifconfigでIPを確認する。
 DHCP環境でIPが割り当てられない場合はudhcpcで割り当ててもらう
 固定IP環境では多分以下コマンドでいけるはず
 ifconfig eth0 <固定IPアドレス>
 ifconfig eth0 netmask <サブネットマスク>

6.SocKit側のLinuxにパスワードを設定する
 ファイル転送にscpを使うのでpasswdコマンドでパスワードを設定する。

7.SocKit側のLinuxにプログラムを転送する。
 scpで実行バイナリを転送する
 コマンドプロンプト上で以下コマンドを実行する
 scp my_first_hps root@<Soc Kit側のIPアドレス>:/home/root
 「my_first_hps」が転送するファイルで「/home/root」が転送先ディレクトリ

8.実行バイナリを実行する。
 TeraTerm上で./my_first_hps

root@socfpga_cyclone5:~# ./my_first_hps 
Hello World!

hps_gpio
H_SW0~3でONになっているSWに対応するLEDD10~13が点灯する

f:id:ginnyu-tei:20131106233701j:plain


hps_gsensor Gセンサーの測定結果を出力する

root@socfpga_cyclone5:~# ./gsensor 
===== gsensor test =====
id=E5h
[1]X=-52 mg, Y=-84 mg, Z=932 mg
[2]X=-20 mg, Y=-92 mg, Z=924 mg
[3]X=44 mg, Y=-80 mg, Z=828 mg
[4]X=-56 mg, Y=-900 mg, Z=552 mg
[5]X=-20 mg, Y=-1096 mg, Z=-52 mg
・・・

hps_lcd
LCDに文字と図形を表示する

root@socfpga_cyclone5:~# ./hps_lcd 
Graphic LCD Demo

f:id:ginnyu-tei:20131106235427j:plain