第6回課題
C言語編
gentest.h内で謎のマクロが飛び交っていますが使い方だけなら簡単です
GT_UUT(adder){ return i1 + i2; }
こんな感じのuutadder.cがあると思います。これは
myfadd(uint32_t i1, uint32_t i2){ return i1 + i2; }
だと思ってだいたいOKです。uint32_tは32ビット長のデータ型という意味で、これをfloatのビット列に見立てて、IEEE754に従うように加工して返すという課題です
すなわち
GT_UUT(adder){ uint32_t s1 = i1 & (1 << 31); uint32_t s2 = i2 & (1 << 31); ... return s3|e3|f3; }
おそらくこんな感じで書いていくことになります
次にtbadder.cですが、
GT_TESTBENCH(adder){ ... }
となっていると思いますが、もちろんこのままでは全然駄目です。 uutが自分で定義した関数へのポインタとなるようにマクロが出来ているので、、 uint32_t o = (*uut)(i1, i2); が自分の関数が返してきた結果です
これを適当にassertしながらループを回して、テストベンチが停止せずに終了すればOKというわけです。 ちなみに、assertは引数がfalseの時、プログラムを停止するのに使うマクロです
ところで初期のi1とi2は00000...00000 ~ 00000...00100までしか動かないので、当然問題があります。(そもそもこれでは16通りしか無いし。)
しかし、これを0~10000にしたところで事態は解決しません(偏った値での検証となる)。のでrand...は0 ~ RAND_MAXしか返さないので、最上位ビットが立つことがなく、これもダメです。xorshiftやメルセンヌツイスタを使うのがおすすめ。
また、非正規化数に対応しない場合は、入力か出力いずれかが非正規化数の時は弾くのを忘れずに。isnormalマクロが便利
C言語のはまりどころ
32ビット長の型をn(> 31)ビットシフトすると、n % 32ビットしかシフトされないようです(warningも出るが..)。気をつけましょう
ハードウェア編
variable, for, whileなどは罠なので封印しましょう。 C言語をそのままVHDLに落とそうとするとvariable無双したくなりますが、全然駄目です(たぶん)
DFFで挟んで周波数うんぬん、、、というのは、なにもしなくてもISEが教えてくれるので利用しましょう。
if文、case ... when文はすべての場合を網羅しないと、ある入力に出力が返せない -> ラッチだ! とISEさんがおせっかいを焼くので気をつけましょう(必ずelse や when othersを書く)。
プライオリティエンコーダは
case hoge is when "1------------------------" => ... when "01-----------------------" => ... ...
と直感的には書きたくなりますが、-はそういう意味ではないようです(論理合成ツールが好きな方に決めていいという意味。実行時には1つに決まる)。残念。