たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

CPUが出来た

習慣化しないとマズい

CPU_final1
↓↑
CPU_final2

三日に一度ぐらいとは

ご利用は計画的に

ソフトウェア開発の現場でデスマーチになるなんて言うのはよーく聞く話で
www.itmedia.co.jp

それについての講義もあるわけですが
どういうスカポンタンがやったら納期遅れになるのっておもってましたよ

あるいは

Twitterで締め切りに追われるクリエイターさん達が死を呟いているのを見て
どういうスケジュールならこうなるのっておもってましたよ

なるね

なんていうかデスマーチになりかけたよ

どういう道のりを歩んだか

僕のチームは僕含めて4人でした。
命令セットが公開されてはいスタートって言われたのが10月の半ばでした。
その日に決まったことといえば
 「パターソン&ヘネシーの本で題材になっていたMIPSアーキテクチャに命令セットが似ているから、それ真似よう」
ということだけでした。

滑り出しが悪かったからかしばらくメンバー間であまり情報交換などがありませんでした。
必須仕様などの理解も全員が出来ていなかったし、そもそもMIPSのRTLがなぜああなっているのかについて解っていない感もありました。

やべえ と思ったので僕が主導してRTL設計を進めていました。しかし今思えばここの時点で僕が結構しくじっていました。
というのも

  • なぜ僕がこういう設計をしたのかメンバーに理解させきれてない。
  • 僕がメンバーに解ったかどうかについて聞いてない。

などですかね。まぁほかにもあるかもしれませんが・・・・

これがどういうことになるかというと

最初があんまりわからない→次もちょっとわからない→わからない→わからない→・・・・→無
オートマトンの状態遷移図で書くとこうです
CPU_final3

解らない状態でVerilogに手を出しても1ミリも設計はすすみません。
実際、わかっている僕(設計に自信なし)がほとんどのモジュールを書きました。

他のメンバーには書いてあるモジュールについてテストをしてもらうように頼んでいました。
しかし自分がやった方がはやいということになりがちでした。

他人の時間を拘束することの難しさ

そいつにはそいつの集中力とかやる気が満ち溢れる時間が違うし、バイトとかもあるだろうし
自分のやってほしいことをその人にやらせる強制力というか支配力?なんて言ったいいのか

結果はすぐ帰ってこないしデバッグは自分でもできるし、そっちの方が速い→自分でやる
まぁそうするとメンバーは余計わからなくなるわけですが。

指定問題を解くために

指定問題が3問ありました。
簡単に言うと

  • 20000=n(n+1)/2を求める問題
  • 最小値探す奴
  • 選択ソート

これらを解く必要がありました。この内、最小値と選択ソートは同一の問題であるとして特化した設計にしました。
どうするかというと 問題を解くための命令を追加してしまう です。

幸い命令セットに予約されていたのは14個で、オペコードは4bitだったので2つ空きがありました。やったぜ

なので、総和とnを求める命令とSTするたびに二つ目のデータメモリにも格納していって選択ソートする命令を追加しました。
これによって圧倒的速さで問題を解けました。

Quartusは敵か味方か

RTL図をもとにゴリゴリつないでいってIverilogのシミュレーションを一通り終わらせたところで、Quartusでボードに焼くためにAnalysisさせました
https://www.altera.co.jp/products/design-software/fpga-design/quartus-prime/what-s-new.htmlwww.altera.co.jp

CPU_final4

ボードで動かせるような構成になっていれば
CPU_final5
という表示が出ますが最初から出るわけもなくここが一番しんどかったです。

なによりボードによるループ回数の制限が苦しかったです。

for (i = 0; i<index-1; i++) begin 
    min=subDM[i];k=i;
    for (j = i + 1; j<index; j++) begin
        if (!Order) begin //昇順
            if (subDM[j]<min) begin 
                min=subDM[j];k=j; 
            end  
        end else begin //降順
            if (subDM[j]>min) begin
                min=subDM[j];k=j; 
            end 
        end 
    end
    subDM[i]<=subDM[k];
    subDM[k]<=subDM[i];
end

まぁこれはよく見る選択ソートの簡単なコードです。言語はVerilogですがCとよく似ているので読めるかと思います。
一見ダメそうなところのない普通のコードですがQuartusはこれにNOを突き付けました。

だめなところ
- ++(インクリメント) - forの条件式に変数index - 配列の参照外になりそうもない配列へのアクセス

それぞれのダメなところは以下のように書き換えねばなりません。

i=i+1
for(i=0;i<32;i=i+1)
if(j<SUBDMMAXSIZE) begin min=subDM[j];k=j; end

特に二つ目のforの条件のところはかなり厳しいです。

今回はボードの制限なのかforwhileでループできる上限は250回まででした。
indexは配列の長さで決まるので何ループするのか わからない これがダメなようです。
初期値が何で``いくつずつ足されて``いつ終わるのかいつも確実でないといけないわけです。

これがきっつい、ループ回数が明確でないといけないので定数を入れるしかありません。
しかしループはあるところで終わってほしい・・・
そこで僕が取った行動は

begin : LOOP
    for(i=0;i<32;i=i+1) begin
        if(i==index)begin
            disable LOOP
        end
    end
end

ifforbreakする意味の解らない方法です。
これのおかげでエラーは消えましたが別の問題が・・・・

ifが増えすぎた

ifが増えるとどうなるかっていうと、回路が複雑で大きくなります。当然です。

result=Rd_data+disp4;

CPU_final6

if(add)begin
    result=Rd_data+disp4;
end else begin
    result=Rd_data-disp4;
end

CPU_final7

まあこういうことです。

3つ目の対策と合わせるとif文がINF個になってしまいました。
指定されたQuartusのバージョンが9.1(32bit)ということもあって、Analysisが全く終わりませんでした。なくなくリジェクト

データメモリの初期化がうまくいかない

FPGAボードに割り当てた回路のリセットボタンを押したときに、データメモリの中の初期値を設定してくれるものがあります。
初期値はMIF(Memory Initialize File)という形式で記述されて、ビルド時にそれが読み込まれます。
しかし、これがうまくいかない。

具体的には データメモリの1番地だけがボードごとに値が変わる のである。

いみわかんないw

指定問題の中にはデータメモリの中から最小値を見つけるようにというものがあったんですが
この1番地が勝手に変わる問題のせいで 最小値がボードごとに変わる。

他ゼミにも聞いたところ同じような現象が起こっており、Quartusのバージョンを15にすると直ったという。

はいもうね現行バージョン16なのに9.1使えって何事よって思ってたんですけど。
こういうこと起こるんですよ。課題渡す前に自分たちで一度やってほしいですね。まぁ無茶でしょうけど・・・

ボード手前まで来てQuartusにいじめられる世界。
焼いてもいじめられる世界。
FPGAは難しい・・・

結果は

追加命令のおかげで問1である総和の問題は超高速で解けました。
他が1200クロックぐらいかかって居るところを13クロックで終了させました。

問2に関してもデータメモリの初期化不良を除けば解けていました。
これも250クロック以上かかっているところを109クロックで終わらせました。

しかし教授陣には難色を示されました。いままで命令を追加されるなんて言うことが無かったみたいで、扱いに困っていましたね。
まぁプロジェクト概要にも追加しちゃダメって書いてなかったので僕の勝ちです。

普通に勝負していたら他ゼミにたぶん負けていた気がします。みるのはクロック数だけらしいので・・・

今回のプロジェクトは本当に力になった気がします。それはVerilogFPGAの知識だけでなくメンバーとどう連携を取っていくかなども含めてです。
来年はこれをもとに卒論…頑張りたいですね。