ImpulseCに関する唯一の日本語の解説書。図書館にある。 ※コーディングが微妙つか、読みにくい。マクロもっと使えや、streamの命名とかわかりやすくしろや禿げ ※本を読みながら付けたメモなので、突然話が逸れたりするよ 目次 SECTION 2 †
設計フロー 1.ビヘイビア記述 → ImpluseCで記述 2.ビヘイビアでのシミュレーション、動作合成 → CoDeveloper 3.論理合成 → ISE(XST) 4.配置配線 → ISE(Implement Design) 5.FPGA用のデータの作成 → ISE(Generate Programming File) 6.FPGAへのデータ転送 → ボード付属のオリジナルプログラム(BitCfg)
・SWとHW部分、またはHW部分同士を接続するインターフェイス(co_register_create, co_stream_create, co_siganl_create) ・HW部分の入力・出力(co_port_create) ・プログラム中でのHWになる部分の指定(co_proces_config) ・ビット幅指定を行う宣言(co_unit) ・HW部分を含んだシミュレーションをするための初期化、並びに実行(co_initialize, co_execute)
・Xilinx ピンのアドレスマッピングをUser Constraint Fileで書き込む SECTION 3 †
ImpulseC → ANSI C仕様でのHW/SW協調設計を可能にするライブラリ仕様 設計入力とシミュレーションに安価なGNU、M$などのコンパイラなどのツールが使える CoDeveloper → ImpulseC仕様でのシステム開発をサポートする動作合成を含む開発環境を持つツール Impulse-Cの仕様とCoDeveloperのツールをペアで仕様して、初めてCベースのHW開発ができる
・HelloWorld_hw.c → HWプロセスの中身と各プロセスの接続、mainから読んでいるコンフィグ関数の定義 ・HelloWorld_sw.c → 二つのSWプロセスの中身
・co_stream:一種のFIFO コンフィグレーション関数で三つのプロセス同士の接続情報を記述 ・co_process_create(名前、co_functionプロセスとして使う関数名、引数の数、引数1、引数2, …); 引数をstreamとして、それを介してプロセス同士をつなぐ ・co_process_config(HW化したいプロセス名、アトリビュート(co_loc固定)、定数("PE0"固定)); ・co_architecture_create(任意の文字列、"generic"を使っている場合はgeneric、コンフィグ関数名、コンフィグ関数への引数); ・co_architecture宣言 ・co_architecture co_initialize(int iterations)関数の中身 基本的にはco_architecture_create関数をリターンするだけ VHDLラッパーは、VHDLにだけ存在する特定のファイルではなく、Verilogでも書くことができる。 ちなみに、VHDLとVerilogを見分けるのは、"process"やファイルの先頭にlibrary ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; SECTION 4 †
VHDLのラッパーファイルとかよくわかんなかったので、Led_Selという1011などの値を常に出しておくプロセスを作成。LEDの列を選択するようにした。結構かかった
P.117 co_signal宣言 co_signal:バスのリクエストとアクノレッジの関係のようなもの。片方のプロセスから1クロック分のリクエストが出力されると、リクエストを受けたプロセスからアクノレッジが1クロック分出力される。 +-----------+ +-----------+ | | ----------(Request)---------> | | | process A | | process B | | | <-------(Acknowledge)-------- | | +-----------+ +-----------+ co_signal_create(const char *name):シグナルのクリエイト co_signal_post(co_signal signal, int32 val):val=メッセージを別のプロセスに送る co_signal_wait(co_signal signal, int32 *ip):別のプロセスのco_signal_postからのメッセージを待つ。 ※※※co_signalのコンフィグに関して※※※ 理由がよく分からないのだが、co_process_configをシミュレーション時に行うと、cosim_logwindow_initでエラーが発生してしまう。 回避方法としては、 #ifdef IMPULSE_C_SYNTHESIS co_process_config(time_tick_process, co_loc, "PE0"); #end として、シミュレーションから外す これに関連して、co_error.hとerrno.hをインクルードしておく。 使い方 printf("%s", strerror(co_errno)); SECTION 5 †
int32 co_register_get(co_register reg):regの値をint32で読み取る void co_register_put(co_register reg, int32 value):regにint32でvalueを書き込む SW <-> HW : register, stream, signal HW <-> HW : register, stream, signal
!co_process_create内の引数は、入力順をしっかり対応させる! モジュールのインスタンス化の際に、direction_real_enの部分を1'b1に置き換える。 assign p_counter_process_direction_value = counter_direction_value; defparam inst1.datawidth = 1; cregister inst1( .clk(clk), .input_en(1'b1), .input_data(direction_real_data), .output_data(counter_direction_value) ); SECTION 6 †P.186
※〜ここ重要〜※ Block化:Cのソースを制御文と制御文の間で分割 最適化単位のBlock化は、Cのソースを走査して制御文に到達する、あるいは制御ブロックから出るごとに、それまでの部分を一つの最適化単位ブロックとしている。 つまり、最適化単位ブロックには、代入文と演算のみが含まれることになる。 ※制御文:while, for, if, switch文のこと。「}」も制御文の切れ目として扱う。 Stage化:各Blockを少ないクロックで処理する 単位ブロックを最小のクロックで処理するように分析して、最終的にステージとしている。つまり、各1クロックでの処理対象をステージという。 各ステージには、ステートマシンの各ステートが割り当てられる。 Tools -> Stage Master Exploereを使う 例:時間の桁分けをDIVでやった場合 |---------------------------------------- | Clock |---------------------------------------- | | Block #0: | Stages: 1 | Max. Unit Delay: 0 | | +------------------------+ | Block #1 loop: | sec60++; | | Stages: 10 | if(sec60 == 60){ | | Max. Unit Delay: 7 | | | +------------------------+ | | +---#2に対応するコード---+ | Block #2: | sec60 = 0; | | Stages: 1 | min60++; | | Max. Unit Delay: 7 | if(min60 == 60){ | | +------------------------+ | | +----#3に対応するコード----+ | Block #3: | min60 = 0; | | Stages: 1 | hour24++; | | Max. Unit Delay: 7 | if(hour24 == 24){ | | +--------------------------+ | | +------------------#4に対応するコード------------------+ | Block #4: | hour24 = 0; | | Stages: 1 | IF_SIM(if (iterations++ == 2) break;) | | Max. Unit Delay: 0 | } | | | } | | | } | | +------------------------------------------------------+ | | +---#5に対応するコード---+ | Block #5: | sec10 = sec60 % DIV; | | Stages: 2 | sec6 = sec60 / DIV; | | Max. Unit Delay: 32 | min10 = min60 % DIV; | | | min6 = min60 / DIV; | | | hour10 = hour24 % DIV; | | | hour3 = hour24 / DIV; | | +------------------------+ | | Block #6: | Stages: 3 | Max. Unit Delay: 0 | Block #7: | Stages: 3 | Max. Unit Delay: 0 | Block #8: | Stages: 1 | Max. Unit Delay: 0 | Block #9: | Stages: 1 | Max. Unit Delay: 0 |---------------------------------------- | Operators: ← 使用したオペレータとデータパス幅のまとめ | 3 Adder(s)/Subtractor(s) (6 bit) | 6 Divider(s) (32 bit) | 1 Comparator(s) (2 bit) | 3 Comparator(s) (7 bit) |---------------------------------------- ※パイプライニングが適用された場合 See ImpulseC-syn-report-howto-read.ppt | Block #1 pipeline: ← パイプライン化ブロック | Latency: 3 ← パイプライン段数 | Rate: 2 ← 1つの出力が得られるサイクル数 | Max. Unit Delay: 148 | Effective Rate: 296 ← 1つの出力が得られる総ユニットディレイ。最適パイプライン化のための、効率比較の基準値小さいほど良い | Rate × Max. Unit Delay | ------ Yngwie J. Malmsteen様用しおり j∬-●3●)ハ < 今日はここまで読んだ メモはメモ †Vertex4のI/Oスタイル PAD→外に出ている配線 OUTBUF→スレッショルドが変更できる。(変更するのはボードを設計したりする時) ImpulseCのエラーとその対処 †ERROR: Stream "sim_led_sel" must be created and opened with the same data type →対応するco_stream_openの幅が間違っている。 UINT_TYPE(hoge)を確認 →プロセス作成時の引数宣言の順番と、コンフィグ時の引数の順番が合致していない プログラミング全般に関して †・関数は出来るだけ短く。100行くらい ・コメントを書く ・組み込み関数を出来るだけ使う ・変数や関数には分かりやすい名前をつける ・意味を示さない関数名、変数名の使用はダメ。ゼッタイ ・定数はできるだけマクロ ・マクロ用のヘッダーファイルを作る ・switch文のcaseは直接定数値でなく、マクロにする(せめてコメント) ・配列のサイズは適切に。ちゃんと最大サイズを調べる ・下手な関数をわざわざ作らなくても、標準関数を使う ・ポインタを理解していない。(ImpulseCには関係ないかな) 個人的なImpulseCの記述時の取り決め †sim_:コンフィギュレーションにおいては、シミュレーション時に使うものは(#ifndef IMPULSE_C_SYNTHESIS)はsim_をつける real_:コンフィギュレーションにおいては、ハードウェア時に使うものはreal_をつける common_:コンフィギュレーションにおいては、シミュレーション時にもハードウェア時にも使うものはcommon_をつける ImpulseC_MACROs:マクロは出来るだけ、このマクロ用のヘッダーファイルに集める co_architecture_create:ここの第一引数""は最初に名前を付けてはいけない*[[ImpulseC/CoDeveloperについて]] きょう:2万人 きのう:0万人 ぜんぶ:247万人 |