-[[【実践】C言語による組込プログラミングスタートブック 鳥海佳孝【著】>http://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5-C%E8%A8%80%E8%AA%9E%E3%81%AB%E3%82%88%E3%82%8B%E7%B5%84%E8%BE%BC%E3%81%BF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%83%96%E3%83%83%E3%82%AF-%E9%B3%A5%E6%B5%B7-%E4%BD%B3%E5%AD%9D/dp/4774129151]]
ImpulseCに関する唯一の日本語の解説書。図書館にある。
※コーディングが微妙つか、読みにくい。COLOR(WHITE):マクロもっと使えや、streamの命名とかわかりやすくしろや禿げ
※本を読みながら付けたメモなので、突然話が逸れたりするよ
目次
#contents
*SECTION 2 [#r7cef2b0]
-2-1-1 ハードウェア設計フロー
設計フロー
1.ビヘイビア記述 → ImpluseCで記述
2.ビヘイビアでのシミュレーション、動作合成 → CoDeveloper
3.論理合成 → ISE(XST)
4.配置配線 → ISE(Implement Design)
5.FPGA用のデータの作成 → ISE(Generate Programming File)
6.FPGAへのデータ転送 → ボード付属のオリジナルプログラム(BitCfg)
-2-1-2 Impulse Cの関数
・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)
-2-1-5 FPGAのピン固定
・Xilinx ピンのアドレスマッピングをUser Constraint Fileで書き込む
*SECTION 3 [#c1dcf7c2]
-3-1-1 ImpulseCとCoDeveloperの違い
ImpulseC → ANSI C仕様でのHW/SW協調設計を可能にするライブラリ仕様
設計入力とシミュレーションに安価なGNU、M$などのコンパイラなどのツールが使える
CoDeveloper → ImpulseC仕様でのシステム開発をサポートする動作合成を含む開発環境を持つツール
Impulse-Cの仕様とCoDeveloperのツールをペアで仕様して、初めてCベースのHW開発ができる
-3-3
生成されたファイルの役割
・HelloWorld.c → いわゆるCのプログラムのmainに当たる部分
・HelloWorld_hw.c → HWプロセスの中身と各プロセスの接続、mainから読んでいるコンフィグ関数の定義
・HelloWorld_sw.c → 二つのSWプロセスの中身
-3-3-2 HW部のリソース(HelloWorld_hw.c)
・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 [#we8ed8bb]
-4-1, 4-2 カウンタの値を7セグメントLEDに出力させる
VHDLのラッパーファイルとかよくわかんなかったので、Led_Selという1011などの値を常に出しておくプロセスを作成。LEDの列を選択するようにした。結構かかった
-4-3-1 co_signalによる時間制御
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 [#v5d98a38]
-5-1-1 アップダウンカウンタへの仕様の変更
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
-> HW -> : port(input, output)
!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(direction_real_en),
.input_en(1'b1),
.input_data(direction_real_data),
.output_data(counter_direction_value)
);
// assign diction_real_en = 1'b1; 危ない希ガス
*SECTION 6 [#k361c921]
P.186
-6-3-2 回路的に大きな部分はないか?
COLOR(RED):※〜ここ重要〜※
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)
|----------------------------------------
※パイプライニングが適用された場合 COLOR(BLUE):See Impulse_C-syn-report-howto-read
※パイプライニングが適用された場合 COLOR(BLUE):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●)ハ < 今日はここまで読んだ
*メモはメモ [#z575e8a8]
Vertex4のI/Oスタイル
PAD→外に出ている配線
OUTBUF→スレッショルドが変更できる。(変更するのはボードを設計したりする時)
*ImpulseCのエラーとその対処 [#ld5319cd]
ERROR: Stream "sim_led_sel" must be created and opened with the same data type
→対応するco_stream_openの幅が間違っている。
UINT_TYPE(hoge)を確認
→プロセス作成時の引数宣言の順番と、コンフィグ時の引数の順番が合致していない
*プログラミング全般に関して [#uab0c900]
-[[改訂新版 Cプログラミング診断室>http://www.kojima-cci.or.jp/fuji/mybooks/cdiag/index.html]]より
・関数は出来るだけ短く。100行くらい
・コメントを書く
・組み込み関数を出来るだけ使う
・変数や関数には分かりやすい名前をつける
・意味を示さない関数名、変数名の使用はダメ。ゼッタイ
・定数はできるだけマクロ
・マクロ用のヘッダーファイルを作る
・switch文のcaseは直接定数値でなく、マクロにする(せめてコメント)
・配列のサイズは適切に。ちゃんと最大サイズを調べる
・下手な関数をわざわざ作らなくても、標準関数を使う
・ポインタを理解していない。(ImpulseCには関係ないかな)
*個人的なImpulseCの記述時の取り決め [#kd06c0fa]
sim_:コンフィギュレーションにおいては、シミュレーション時に使うものは(#ifndef IMPULSE_C_SYNTHESIS)はsim_をつける
real_:コンフィギュレーションにおいては、ハードウェア時に使うものはreal_をつける
common_:コンフィギュレーションにおいては、シミュレーション時にもハードウェア時にも使うものはcommon_をつける
ImpulseC_MACROs:マクロは出来るだけ、このマクロ用のヘッダーファイルに集める
co_architecture_create:ここの第一引数""は最初に名前を付けてはいけない*[[ImpulseC/CoDeveloperについて]]
きょう:&counter(today);万人
きのう:&counter(yesterday);万人
ぜんぶ:&counter(total);万人