Altifigence Academy

6 / 20 · 実習

実習:符号付きMAC処理要素

独立したモデルで有効なオペランド、ストール、クリアを検査します。

1個のPEの契約を実行する

これをpe-lab.mjsとして保存し、Node.jsでnode pe-lab.mjsを実行してください。外部パッケージは使わず、PE lab passedと表示します。算術と制御のモデルを検査するもので、SystemVerilogのコンパイルやDDSでの実行を示すものではありません。通常の2項のジョブはW=8、K=2、AW=17と考え、モデルの参照値には広い整数を使います。

PEはAとBそれぞれのvalidフラグを受け取ります。両方がtrueのときだけ累積します。転送は各オペランド自身のvalidに従います。後のレッスンでタグを追加し、有効な2つのオペランドが同じ縮約項に属することを確認します。

javascript
import assert from 'node:assert/strict';
const pe = {acc:0,a:0,b:0,av:false,bv:false};
function edge({a=0,b=0,av=false,bv=false,
               advance=true,clear=false,reset=false}={}) {
  if (reset || clear) {
    Object.assign(pe,{acc:0,a:0,b:0,av:false,bv:false});
  } else if (advance) {
    if (av && bv) pe.acc += a*b;
    Object.assign(pe,{a,b,av,bv});
  }
  return {...pe};
}
edge({clear:true});
assert.equal(edge({a:-2,b:3,av:true,bv:true}).acc,-6);
const held={...pe};
assert.deepEqual(edge({a:99,b:99,av:true,bv:true,advance:false}),held);
assert.equal(edge({a:4,b:-5,av:true,bv:true}).acc,-26);
assert.equal(edge({a:8,b:8,av:true,bv:false}).acc,-26);
assert.equal(pe.av,true); assert.equal(pe.bv,false);
edge({clear:true,a:100,b:100,av:true,bv:true});
assert.equal(pe.acc,0); assert.equal(pe.av,false);
assert.equal(edge({a:-128,b:-128,av:true,bv:true}).acc,16384);
edge({reset:true,advance:false});
assert.deepEqual(pe,{acc:0,a:0,b:0,av:false,bv:false});
console.log('PE lab passed');

結果を予測し、確かめる

最初の対は−6です。停止では提示された99を無視し、すべての状態を保持します。次の有効な対は−20を加え、−26に達します。相方のないAトークンは転送されますが、MACには寄与しません。クリアは同時の有効な対より優先し、その後の最小×最小は16384になります。advanceがfalseでも、リセットはvalid状態をクリアします。

明示的に符号付きの積と加数信号を用い、同じ優先順位をalways_ffで表してください。アレイをモデル化するときは更新前の状態を読み、別の次状態に書き込みます。PEオブジェクトをその場で更新すると、1エッジ中にトークンが複数のPEを横断してしまう可能性があります。

累積条件をANDからORに変えてみてください。相方のないトークンのアサーションは失敗するはずです。また、advanceをアキュムレータだけに適用し、転送は動かしてみてください。各アサーションが守る契約を説明します。成功メッセージだけでは学習成果として十分ではありません。

提示オペランドと消費オペランドを別々に記録します。停止中の99はインターフェースに見えますが、決して消費されません。ラッパはadvance再開まで次の予定項を保持する必要があります。返された状態コピーが前の観測を保存します。波形テストベンチへ検査を移すときは、アキュムレータだけでなく転送validフラグも確認します。

実際のRTL:符号付きMAC PE

添付のsigned_mac_pe.sv、systolic_2x2.sv、tb_systolic_2x2.svを一緒に保存します。最初の2ファイルは合成可能RTL、テストベンチはシミュレーション専用です。PEは完全な2Wビット積をAWへ符号拡張してから累積します。W=8,K=4の検査はAW=18を使い、65536、−65024、64516を確認します。順序付きkタグはprotocol_errorで不一致項を拒否します。

優先順位はreset、clear、advanceです。最初のデータエッジ前にクリアを完了します。各立ち上がり後に更新アキュムレータを観測し、隣は次のadvanceエッジでレジスタ転送を消費します。停止はすべての値、valid、タグ、countを保持します。クリア間に1ジョブを実行し、出力量子化やDDS統合はありません。

Icarus Verilogをインストールした環境で実行します。

bash
iverilog -g2012 -s tb_systolic_2x2 -o systolic.vvp signed_mac_pe.sv systolic_2x2.sv tb_systolic_2x2.sv
vvp systolic.vvp

RTL PASS:を期待し、失敗は$fatalで終了します。加数をゼロ拡張へ変更し、負行列の失敗を再現します。最初に不一致になるPEアキュムレータを説明し、符号拡張へ戻して再実行します。NodeとHDLのログは別々に残します。

自分で考えてみましょう

(−2,3)と(4,−5)の間に有効な対(0,7)を挿入します。和はいくつですか。有効なゼロと無効なトークンの違いは何ですか。

解説を見る

和は−26です。有効なゼロも実際のk項を消費し、項数とタグを進めます。無効なトークンは項を消費しません。3項のジョブではK、幅の分析、完了制御を対応して更新します。

Lesson files

pe-lab.mjs ↓signed_mac_pe.sv ↓systolic_2x2.sv ↓tb_systolic_2x2.sv ↓

選択はこのブラウザに適用されます。フッターからいつでも変更できます。