Normalize underflow【NandGame編】
はじめに
いつもブログをご覧いただきありがとうございます。
コーストFIRE中のIPUSIRONです😀
Normalize underflowレベル
Normalize underflowレベルのゴールは、入力sfが11桁未満の場合、11桁に変更し、指数もそれに応じて調整する回路を実装することです。この調整処理をアンダーフローの正規化(normalize underflow)と呼ぶようです。
入力 | ・exp:指数 ・sf:仮数 ※0ではなく、最大11桁と仮定する。 |
出力 | ・exp:調整済みの指数 ・sf:調整済みの仮数 |
Normalize underflowレベルを解く
1:入力sfが11桁未満(10桁以下)かどうかを識別する方法を検討する
入力sfは最大11桁と仮定されていました。
つまり、11桁と10桁以下のパターンに分けられます。
10桁以下を識別するには、11桁目である10ビット目(右から0スタート)がゼロかどうかを調べればよいでしょう。
splitterコンポーネントを通して、10ビット目にis zeroコンポーネントを接続します。
is zeroコンポーネントの出力が1なら10ビット目がゼロ、すなわち10桁以下であることを判定できたことを意味します。
10桁以下の時は入力expとsfを調整してから出力する必要があります。これについてはステップ2で実装しましょう。
対して、11桁であれば入力expとsfはそのまま出力(リレー)すればよいことになります。
expとsf用として2つのセレクターを配置します。「select 16コンポーネントの判定ビットs」と「is zeroコンポーネントの出力」を接続します。11桁ということは、is zeroコンポーネントの出力が0になります。つまり、リレーするだけであれば「select 16コンポーネントのD0」を使うことになります。
ここまでを回路に組み込みます。
※実はis zeroコンポーネントを使わずに、10ビット目をselect 16の制御ビットsに接続しても構いません。その場合は10ビット目がゼロなら10桁以下になり、調整時はD0を使うことになります。このアプローチはステップ3で解説します。
2:入力sfが10桁と仮定して回路を組んでみる
sfは1桁左シフトします。
expは1減らします。デクリメントや減算用のコンポーネントが用意されていないので、補数を使って減算を実現するしかありません。具体的にいえば、addコンポーネントでffffhを加算することになります。
以上を回路に組むと次のようになります。
テストしてみると、入力sfが10桁のときにはパスしていますが、9桁の場合には失敗しています(当たり前)。
・9桁であれば、sfを2桁左シフトし、expから2を引く。
・8桁であれば、sfを3桁左シフトし、expから3を引く。
・・・
といった処理を実現しなければなりません。
処理内容はわかりやすいですが、実際にそれを回路で実現しようとすると複雑になります。
3:現時点での回路を最適化する
これ以降は回路が複雑になる予定ですので、現時点でコンポーネントを減らしておきます。
is zeroコンポーネントは冗長なので除去します。その代わり、10ビット目をセレクターに直結し、D0とD1の入力を逆転させます。テストを実行して、先と同じ2番目のテストまでパスすることを確認してください。
※以降、その他の桁の判定でもis zeroコンポーネントを使わない方針でいくため、回路が少しすっきりするはずです。
4:カスタムコンポーネントを用意する
次のカスタムコンポーネントを準備します。名前を"nu1-expn"としました。
5:カスタムコンポーネントを活用して回路を実装する
6:テストする
テストにパスするとクリアになります。
例えば、sf=Fh(=1111b)、sf=9h(=1001b)の2つのパターンを試してみてください。
出力expが8hのままで変化しません。
つまり、仮数において左から見ていき1が登場する位置のみを正しく検出できています。
クリアはできるけどバグありの回路【おまけ】
このカスタムコンポーネント名を"adjust exp"とします。
最終的にテストはパスしますが、adjust expコンポーネントにはバグがあります。
例えば、sf=Fh(=1111b)とsf=9h(=1001b)の場合で出力が一致しないといけませんが、そうなりません。