2
1

機械語から理解するMN-Core

Last updated at Posted at 2024-08-18

もうすぐコンテストがあるそうなので、予習してみました。(書きかけです)

機械語の読み方

引数を設定してvsmファイルをアセンブラに投げると読みやすくなる

--print-asmをつけるとコードの後ろに元の命令がコメントで付く

$ /assemble3 hello.vsm --print-asm
i 01000000...000000000000001100000000000000 # imm ui"0" $n0

--print-csvをつけると、フィールドごとに分割してくれる

i,ll,pe.mrc.imr,pe.mrc.wl,...,l2bm.darwrite,wd
m,valid,mmode,tmode,...,adrb,nw,priority
i,="01",="00000",="0",="0",="0",="0",...,="000",="11",="0000",="0",="0",="00000000",

一行目はi命令のコラム名一覧で、二行目はm命令のコラム名一覧になる。

i命令はPE命令のauto strideモードの機械語
m命令はMV命令の機械語

ここではi命令だけに注目する

PE命令のフィールド

PE命令は以下のフィールドを持つ

PE命令
i ll pe l1bm l2bm wd
mrc trc rfc0 rfc1 lm0 lm1 mauc aluc
i 2bit 20bit 3bit 41bit 41bit 32bit 31bit 29bit 17bit 40bit 28bit 8bit

各フィールドに対応するコンポーネントは以下のようになる

フィールド コントローラ
pe.mrc マスクレジスタ
pe.trc Tレジスタ(t)
pe.rfc0 RF0レジスタ(r)
pe.rfc1 RF1レジスタ(s)
pe.lm0 LM0メモリ(m)
pe.lm1 LM1メモリ(n)
pe.mauc MAU
pe.aluc ALUC
l1bm L1BM(b)
l2bm L2BM(c)

さらに細かいフィールドは各コンポーネントごとに記述する

PE命令の複数の出力オペランド

PE命令は複数の出力オペランドを指定できる。これは以下のような仕組みでコード化する。

例としてALUの計算結果を複数の出力先(t, r, s, m, n)に保存する命令は

PE命令
i ll pe l1bm l2bm wd
mrc trc rfc0 rfc1 lm0 lm1 mauc aluc
i - - write=1 write=1 write=1 write=1 write=1 - ALUOP - - -
isel=ALU isel=ALU isel=ALU isel=ALU isel=ALU

このようにalucで計算を指定し、各々の出力先(trc, rfc0, rfc1, lm0, lm1)の書き込みを有効にし(write=1)、入力セレクタにALUを指定(isel=ALU)する。

同様にMAUとALUで計算して結果を(r, s, t, m, n)に分けて保存したい場合は

PE命令
i ll pe l1bm l2bm wd
mrc trc rfc0 rfc1 lm0 lm1 mauc aluc
i - - write=1 write=1 write=1 write=1 write=1 MAUOP ALUOP - - -
isel=MAU isel=ALU isel=MAU isel=ALU isel=MAU

のようにコード化される。このコード化により複数出力オペランドが可能となる。

PE命令の入力オペランド

ALUは2つの入力オペランドAとBを持つ。命令によってオペランド数は0、1、2の場合がある。
MAUは3つの入力オペランドAとBとCを持つ。命令によってはBは行列となり、行列レジスタxかyを使う。

例えば、ALUの入力オペランドAがrの場合は次のようにコード化する。

PE命令
i ll pe l1bm l2bm wd
mrc trc rfc0 rfc1 lm0 lm1 mauc aluc
i - - - radr=アドレス - - - - ALUOP - - -
isela=r

このようにコード化する。出力オペランドのときとは逆にALU側のiselを設定し、データソース側はアドレスを指定する。

ALUとMAUがrから同じデータを受け取って計算する場合は次のようにコード化する。

PE命令
i ll pe l1bm l2bm wd
mrc trc rfc0 rfc1 lm0 lm1 mauc aluc
i - - - radr=アドレス - - - MAUOP ALUOP - - -
isela=r isela=r

このように同じアドレスを読む限りで、MAUとALUに同時にrから入力可能となる。

ALUのポートA

ALUのポートAは以下の入力をiselに指定できる。このポートは$peidなどの固定値を指定できる。(TODO: 15個しかないので1つ忘れてるかも???)

入力
r
s
t
m
n
$peid
$l1bid
$l2bid
$msb1
$subpeid
$mabid
$mauf
$aluf
$lbf
$mreadf

ALUのポートB

ALUのポートBは以下の入力をiselに指定できる。Aと異なり固定値は指定できないのと$mreadfも指定できない。

入力
r
s
t
m
n
$mauf
$aluf
$lbf

MAUのポート

MAUのポートは以下の入力をiselに指定できる。ALUのポートBと同じ。

入力
r
s
t
m
n
$mauf
$aluf
$lbf

TRC

Tレジスタの制御を行う。

フィールドは以下の通り。

pe
trc
write isel
1bit 2bit

write=1のときはiselで指定した入力から書き込みを行う。そうでないときは読み出しのみ行う。

アドレス指定やワード長指定はなく、2長語×4サイクルのアクセスで固定。(TODO: iselの計算結果が1長語のときを調べる)

iselに指定できる入力

isel
MAU
ALU
L1BM
MREAD

ハザード: 書き込み後は1ステップ休む

RFC0とRFC1

レジスタファイルの制御を行う。

フィールドは以下の通り。

pe
rfc0/rfc1
write isel wadr wadri wwl radr radri rwl
1bit 2bit 9bit 8bit 2bit 9bit 8bit 2bit

write=1のときはiselで指定した入力から書き込みを行う。そうでないときは読み出しのみ行う。

wadrwadriwwlで書き込みアドレス、書き込みアドレス増分、書き込みワード長を指定する。
radrradrirwlで読み出しアドレス、読み出しアドレス増分、読み出しワード長を指定する。

アクセスするアドレスはサイクルごとに

サイクル アドレス
0 adr + adri * 2 * wl * 0
1 adr + adri * 2 * wl * 1
2 adr + adri * 2 * wl * 2
3 adr + adri * 2 * wl * 3

コード例(TODO: 動作確認して)

コード adr adri wl アドレス
$lr4 4 0 1 (4, 4, 4, 4)
$lr4v 4 1 1 (4, 6, 8, 10)
$lr4v2 4 1 1 (4, 6, 8, 10)
$llr4v4 4 1 2 (4, 8, 12, 16)

iselに指定できる入力

isel
MAU
ALU
L1BM
MREAD

ハザード: 書き込み後は1ステップ休む(アドレスごとに独立)。

続きはまた書く

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1