systemc tutorial
Post on 14-Jun-2015
4.015 Views
Preview:
TRANSCRIPT
オレオレSystemC入門@LSI設計雑記帳
※注意事項※
本資料は筆者が所属している団体や組織に関係あるものではありません。
本資料内のソースコードを使って問題が起きても筆者は責任取りません。
楽しく見ていただければ幸いです。
自己紹介
Blog:LSI設計雑記帳http://lsifrontend.blog100.fc2.com/
Twitter:@kocha2012https://twitter.com/kocha2012
GitHub:Kocha https://github.com/Kocha
SystemC is 何
C++のクラスライブラリで
HLSの入力言語だったり、 仮想環境モデリング言語 だったりするのです!
※HLS(High Level Synthsis)
ようこそ! SystemCの世界へ
Hello World
#include <systemc.h> !
int sc_main(int argc, char *argv[]) { !
printf("Hello World!!!\n"); !
return 0; }
Hello World
#include <systemc.h> !
int sc_main(int argc, char *argv[]) { !
printf("Hello World!!!\n"); !
return 0; }
SystemCのヘッダーをinclude
main関数は「sc_main」
Hello World$> ./main ! SystemC 2.3.0-ASI --- Jul 13 2012 06:33:43 Copyright (c) 1996-2012 by all Contributors, ALL RIGHTS RESERVED !Hello World!!!
\(^o^)/できた~
おわり
ってことはなく、 まだまだ続きます!
理解する
設計する
検証する
次回予告
目次
理解する
SystemCとは
SystemCは、プログラム言語であるC++のクラスライブラリとして提供されており、それ自体言語として独立した文法を持つものではない。ライブラリにはハードウェア記述の為の機能、すなわち並列実行の概念やデータ型、それを扱う各種関数が定義されている。それを使って書かれたプログラムは通常のC++コンパイラでコンパイルすることができ、結果生成されたオブジェクトはハードウェアのシミュレータとして動作する。
※Wikipedia(http://ja.wikipedia.org/wiki/SystemC)より
SystemCの適用場面仮想環境:Virtual Platform
ソフトウェア開発環境
トランザクションベース(TLM2.0)
高位合成:High Level Synthsis
SystemC→Verilog HDL/VHDL
サイクルベース
知っておきたいC++基礎
クラスとメンバ
オブジェクト
コンストラクタ
継承(インヘリタンス)
オーバーロード
オーバーライド
多態性 (ポリモフィズム)
テンプレート
※他にもありますが、入門編なので省略
※ポインタ:C言語
SystemCのシステム構成
「モジュール」と呼ばれるデザイン内に
「プロセス」により関数内で機能を記述し
「チャネル」でモジュール間を接続する。
!
各プロセスは同時並列に実行
プロセス内は逐次実行
sc_mainsc_main()
モジュール(SC_MODULE)
sc_main()
モジュール モジュール
モジュール
プロセス(SC_THREAD/SC_METHOD/SC_CTHREAD)
sc_main()
モジュール
プロセス
プロセス
プロセス
モジュール
モジュール
プロセス
チャネル(sc_prim_channel)
sc_main()
モジュール
プロセス
プロセス
プロセス
モジュール
モジュール
プロセス
チャネル
チャネル
プロセス
ポート/インターフェース
設計する
モジュールを作る
プロセスを定義する
機能(処理)を記述する
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
void hoge::process() { out = 0; while(1) { wait(); out = in * x; } };
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
モジュール宣言
#define SC_MODULE(name) struct name : sc_module
※実装はマクロ(struct)
module hoge(...); : endmodule
※Verilog HDL/SystemVerilogでの意味
class hoge : public sc_module { ... };
※classで書く場合(sc_moduleを継承する)
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
モジュール宣言
コンストラクタ宣言
初期化処理を記述する部分
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
コンストラクタ宣言
class hoge; function new(); : endfunction
※SystemVerilogだと new関数
#define SC_CTOR(name) implementation-defined; name(sc_module_name)
※実装はマクロ
SC_MODULE( hoge ) { ... SC_HAS_PROCESS(hoge); hoge( sc_module_name n) : sc_module_name(n) { SC_THREAD( processs ); ...
※マクロを使わずで書く場合
必ず必要
豆知識:初期化リストSC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
SC_CTOR( hoge ): in(“in”), out(“out”) {
書いておくと良いことあるかも!
http://lsifrontend.blog100.fc2.com/blog-entry-432.html
※サブモジュールのインスタンス時など 書かないといけない場合もあります
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
プロセスを定義
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
プロセスを定義
機能(処理)が記述されている関数
void hoge::process() { out = 0; while(1) { wait(); out = in * x; } };
実際の機能(処理)
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
プロセスを定義
引数無しの関数
機能(処理)が動くきっかけを指定 (この例だと in の値が変化したら)
void hoge::process() { out = 0; while(1) { wait(); out = in * x; } };
sensitiveに登録されている 動作待ち
プロセス定義は3種類SC_THREAD
void hoge::process() { ... ... wait(); // wait - in(value) ... ... wait(); // wait - in(value) ... wait(); // wait - in(value) ... }
SC_THREAD( process ); sensitive << in ;
初期動作
Simulation
再度呼び出しなし
・関数から抜けると再度呼び出されないため while文や for文で無限ループを作る
プロセス定義は3種類SC_METHOD
SC_METHOD( process ); sensitive << a << b ;
void hoge::process() { ... ... ... ... ... } !!!初期動作 Simulation
wait - a,b(value)
終了まで繰り返す
・繰り返し実行されるプロセス ・waitは記述出来ない
プロセス定義は3種類SC_CTHREAD
SC_CTHREAD( process, clock.pos() ); reset_signal_is(reset, true);
void hoge::process() { ... ... ... while(1) { wait(); // wait - prosedge clock ... wait(); // wait - posedge clock ... } }
初期動作
reset_signal_isで 設定されていれば強制的に
・SC_THREADをクロックイベント用にしたもの ・関数から抜けると再度呼び出されないため while文や for文で無限ループを作る
プロセス定義は3種類SC_THREAD SC_METHOD SC_CTHREAD
void hoge::process() { ... ... wait(); // wait - in(value) ... ... wait(); // wait - in(value) ... wait(); // wait - in(value) ... }
SC_THREAD( process ); sensitive << in ;
SC_METHOD( process ); sensitive << a << b ;
SC_CTHREAD( process, clock.pos() ); reset_signal_is(reset, true);
初期動作
Simulation
再度呼び出しなし
void hoge::process() { ... ... ... ... ... } !!!初期動作 Simulation
wait - a,b(value)
終了まで繰り返す
void hoge::process() { ... ... ... while(1) { wait(); // wait - prosedge clock ... wait(); // wait - posedge clock ... } }
初期動作
reset_signal_isで 設定されていれば強制的に
初期動作は dont_initialize();で抑制可能 例)SC_THREAD( process ); sensitive << in ; dont_initialize();
sensitive記述は様々SC_THREAD( process ); sensitive << in ;
SC_THREAD( process ); sensitive << in1 << in2 ;
SC_THREAD( process ); sensitive << in1.pos() ; sensitive << in2.neg() ;
SC_THREAD( process ); sensitive << in1.posedge() ; sensitive << in2.negeage() ;
※for文で記述することも出来ます。
(async_)reset_signal_is
reset_signal_is async_reset_signal_is SC_THREAD( process ); reset_signal_is( reset, true);
SC_THREAD( process ); async_reset_signal_is( reset_n, false);
clock
reset
reset_n
リセット期間
リセット期間
※clock立ち上がりエッジ(posedge)の場合
極性信号名
SystemC-2.3から追加
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
入出力ポート(Interface)宣言
module hoge( input bit[31:0] in, output bit[31:0] out ); : endmodule
※SystemVerilogでの意味
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; } };
void hoge::process() { out = 0; while(1) { wait(); out = in * x; } };
out.write(0); while(1) { wait(); out.write( in.read() * x); }
このように動いてます。
out.initialize(0);っと書くことも可能
ポートとチャネルport/interface 接続するchannel
sc_in/out/inout
sc_signal
sc_buffer
sc_clock
sc_fifo_in/out sc_fifo
sc_mutex_if sc_mutex
sc_semaphrore_if sc_semaphore
チャネルはレジスタ(FF)#include <systemc.h> !int sc_main(int argc, char *argv[]) { int a; sc_signal<int> b; ! a = 10; b = 10; std::cout << "a = " << a << ", b = " << b << std::endl; ! sc_start(1, sc_core::SC_NS); std::cout << "a = " << a << ", b = " << b << std::endl; ! return 0; }
実行結果 a = 10, b = 0 a = 10, b = 10
シミュレーション時刻の経過により値が更新される。
(代入はノンブロッキング代入)
チャネルはWire sc_signal<int> x0y0; ! laplacian_filter dut("dut"); testbench tb("tb"); ! dut.clk(clk); dut.x0y0(x0y0); // input : dut.out(y); tb.clk(clk); tb.x0y0(x0y0); // output :
チャネルは用途において、regもしくはwireとなる。
接続(wire)
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
データ型
SC_MODULE( hoge ) { ! sc_in<int> in; sc_out<int> out; ! int x; ! void process(); ! SC_CTOR( hoge ) { SC_THREAD( process ); sensitive << in ; x = 10; } };
データ型
SystemCはC++なので、 C++のデータ型は全て使えます。
SystemCで追加された型データ型 説明 記述例
sc_int<N> Nビット整数 sc_int<8> a = -123;
sc_uint<N> Nビット符号なし整数 sc_uint<8> a = 0xab;
sc_bigint<N> 64ビット以上のsc_int sc_bigint<128> = “0xaaa...”;
sc_biguint<N> 64ビット以上のsc_uint sc_biguint<128> = “0xaaa...”;
sc_bit ’0’, ’1’ の2値 (使用は非推奨) sc_bit a = ‘1’;
sc_logic ’0’, ’1’, ’x’, ’z’の4値 sc_logic a = ‘z’;
sc_bv<N> Nビットの sc_bit sc_bv<8> a = “10101010”;
sc_lv<N> Nビットの sc_logic sc_lv<8> a = “1x101z10”;
sc_fixed<NW, NI> 固定小数点 sc_fixed<8,4> a = -0.25;
sc_ufixed<NW, NI> 符号なし固定小数点 sc_uifixed<8,4> a = -1.75;
独自のデータ型(MyType)
比較演算子bool operator == (const MyType & rhs) const {
代入演算子MyType& operator = (const MyType& rhs) {
トレース関数void sc_trace(sc_trace_file *tf, const MyType & v, const std::string & NAME ) {
出力演算子ostream& operator << ( ostream& os, MyType const & v ) {
class/structに必ず実装するメンバ関数
検証する
sc_main
モジュールをインスタンスする
信号を生成する
変数の値を表示する
タイミング波形を取得する
sc_mainは必須#include <systemc.h> s_in = 0; sc_start(10, SC_NS); int sc_main(int argc, char *argv[]) { cout << "in = " << s_in << ", out = " << s_out << endl; sc_signal<int> s_in, s_out; hoge m_hoge(“m_hoge”); s_in = 10; m_hoge.in(s_in); sc_start(10, SC_NS); m_hoge.out(s_out); cout << "in = " << s_in << ", out = " << s_out << endl; return 0; }
モジュールをインスタンス#include <systemc.h> s_in = 0; sc_start(10, SC_NS); int sc_main(int argc, char *argv[]) { cout << "in = " << s_in << ", out = " << s_out << endl; sc_signal<int> s_in, s_out; hoge m_hoge(“m_hoge”); s_in = 10; m_hoge.in(s_in); sc_start(10, SC_NS); m_hoge.out(s_out); cout << "in = " << s_in << ", out = " << s_out << endl; return 0; }
hoge *m_hoge; m_hoge = new hoge(“m_hoge”); m_hoge->in(s_in); m_hoge->out(s_out);
※別の書き方
信号を生成#include <systemc.h> s_in = 0; sc_start(10, SC_NS); int sc_main(int argc, char *argv[]) { cout << "in = " << s_in << ", out = " << s_out << endl; sc_signal<int> s_in, s_out; hoge m_hoge(“m_hoge”); s_in = 10; m_hoge.in(s_in); sc_start(10, SC_NS); m_hoge.out(s_out); cout << "in = " << s_in << ", out = " << s_out << endl; return 0; }
※sc_in/outの接続は sc_signal
※sc_startでシミュレーション開始
変数の値を表示する
s_in = 0; sc_start(10, SC_NS); cout << "in = " << s_in << ", out = " << s_out << endl; s_in = 10; sc_start(10, SC_NS); cout << "in = " << s_in << ", out = " << s_out << endl; return 0; }
■cout sc_signal - << operator sc_intなど- a.to_string()関数が存在 ■printf sc_intなど- a.to_int()関数が存在 ■sc_report SystemC定義の表示形式関数 !
★sc_time_stamp() で時刻も表示!
タイミング波形を取得#include <systemc.h> s_in = 0; sc_start(10, SC_NS); int sc_main(int argc, char *argv[]) { cout << "in = " << s_in << ", out = " << s_out << endl; sc_signal<int> s_in, s_out; sc_trace_file *tf; s_in = 10; tf = sc_create_vcd_trace_file("waves"); sc_start(10, SC_NS); sc_trace(tf, s_in, "in"); cout << "in = " << s_in sc_trace(tf, s_out, "out"); << ", out = " << s_out << endl; hoge m_hoge(“m_hoge”); sc_close_vcd_trace_file(tf); m_hoge.in(s_in); return 0; m_hoge.out(s_out); } ※閉じることを忘れずに
余談SystemCのシミュレータは無償なので、いつでもシミュレーションできます。Webでも → http://www.edaplayground.com
仮想環境(Virtual Platform/TLM2.0)については別スライドを作成する予定です。
最近、SystemC流行ってます!(ステマ)この機会に是⾮非トライしてみてください!
おわり
top related