2.アーキテクチャ
命令幅、演算語長
設計が簡単なのは32ビット幅です。いきなり32ビットなんて、、と心配する必要はありません。本当に簡単なのは32ビットなのです。8ビットCPUにしようものなら、デコーダが複雑になりすぎます。では、16ビットではどうかというと、非常に簡単なインストラクションしかサポートしないのならいいのですが、後で独自命令を付け加えられることを考えるとやっぱり足りない、実用的かつ、設計が簡単ということを考えるなら、32ビット以上でRISCが、お勧めです。
3オペランドというのは、c=a+bです。つまり、aレジスタ + bレジスタ => cレジスタと言う具合に3つのレジスタ
を、独立に指定できます。これに対し16ビット以下のCPUの殆どは、a=a+bという命令しか実装していません。考え方としてどちらが自然かは自明でしょう。どうしてこのようになったかというと命令フィールドが足りないからです。たとえば、16レジスタあったとして、それを指定するのは、4ビット必要です。それが、独立に3個分要ると12ビットを消費してしまいます。固定長フォーマット16ビット固定を仮定すると、16-12で残り4ビットしかありません。残り4ビットでは、3オペランドを取る限り16命令しか実装できません。ということで、16ビットでも厳しいことが分かると思います。という訳で、32ビットはごくごく自然な結果なのです。
プログラムカウンタ
26ビットにしていますが、手持ちのFPGA内蔵RAMは、16KBしか積めないので実際的には、FPGA搭載RAM容量で制限されてしまいます。外部RAMをアクセスする機構は、実装しておりません。
レジスタ
32x32の32ビットです。リードは2ポート、ライトは1ポート、計3ポートが必要です。Alteraでは、3ポートRAMがありますので、それを使えばよいです。Xilinxでは、3ポートがありません。分散RAMを使えば合成できますが、それをやってしまうとスタータキットでは、リソース不足になってしまうので、どうしてもBLOCK RAMを使わざるえず、3ポートRAMは、使えません。そこで、Xilinxは、同じレジスタファイルを2個使います。ライトは共通とすることで、レジスタファイルの中身は常に同じになります。従って、2ポートRAMx2=>3ポートRAMとして使えることになります。
命令フォーマット
32ビット固定長、5段パイプラインに決定しました。
インストラクション
下表は、インプリメントする全命令です。全命令を5ステージパイプラインで実行します。ジャンプ、ブランチ系命令でブランチした場合3-4クロックかかる他は、メモリのR/Wを含め全て1クロックで実行します。 ただし、ブランチハザード、データハザードは対応していませんので、コンパイラやアセンブラで対応する必要があります。
余談です。MIPS互換を狙って最初から設計したのではないのですが、設計していくうちに同じなってしまいました。GCCの成果を利用できるなら、と割りきりました。CPUのパイプラインの設計は筆者も初めてなのですが、設計を通じてディレイドブランチや、zeroレジスタ、Jump&Link等、RISCだと必ずでてくる言葉の必然性を理解することができました。加えてCPUのどこがCritical Pathかであるか身を持って知ることができました。なにが問題かを知ることができたのは収穫でした。RISCが出た頃、斬新だった手法も、いまや古典の趣があります。MIPS(TM)アーキテクチャは、今やRISC、否CPUの教科書ではないでしょうか?
パイプラインの割付は、Stratixで合成しながら、チューニングするという原始的な方法で行いました。
以下のMIPSインストラクション-Iの内、未実装は赤で示しています。 とりあえず、現サポートの命令セットで、ドライストーン、リードソロモン、等いくつかのCプログラムを走らせましたが、支障はありませんでした。(サポートしていない命令は出現しませんでした。特に、分岐リンク等は、命令の存在意義について筆者は疑問を持っています。加えて現在Critical Pathになっているところに追加なので、なるべくならハードはいじりたくない気分です。GCCのコードジェネレートでなんとかならないでしょうか?)
また、LWL,SWL,LWR,SWRはアラインされていないメモリに対する転送命令ですが、パテントになっており今後共、実装予定はありません。MTHI,MTLOは、恐らく割り込みと乗除算がかさなったときの退避のために存在する命令ですが、現在は乗除中の割り込みを禁止していることと、まともな割り込みコントローラを実装していないのでインプリメントしていません。
ADD -- Add
Description:
| Adds two registers and stores the result in a register(Overflowで例外発生)
|
Operation:
| $d = $s + $t;
|
Syntax:
| add $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5ビット |
6'b100_000 |
|
ADDI -- Add immediate
Description:
| Adds a register and a signed immediate value and stores the result in a
register
|
Operation:
| $t = $s + imm;
|
Syntax:
| addi $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001000 |
5ビット |
5ビット |
16ビット |
|
ADDIU -- Add immediate unsigned
Description:
| Adds a register and an unsigned immediate value and stores the result in a
register
|
Operation:
| $t = $s + imm;
|
Syntax:
| addiu $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001001 |
5ビット |
5ビット |
16ビット |
|
ADDU -- Add unsigned
Description:
| Adds two registers and stores the result in a register
|
Operation:
| $d = $s + $t;
|
Syntax:
| addu $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100_001 |
|
AND -- Bitwise and
Description:
| Bitwise ands two registers and stores the result in a register
|
Operation:
| $d = $s & $t;
|
Syntax:
| and $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100100 |
|
ANDI -- Bitwise and immediate
Description:
| Bitwise ands a register and an immediate value and stores the result in a
register
|
Operation:
| $t = $s & imm;
|
Syntax:
| andi $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001100 |
5ビット |
5ビット |
16ビット |
|
BEQ -- Branch on equal
Description:
| Branches if the two registers are equal
|
Operation:
| if $s == $t PC +=imm << 2;
|
Syntax:
| beq $s, $t, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000100 |
5ビット |
5'h0 |
16ビット |
|
BGEZ -- Branch on greater than or equal to zero
Description:
| Branches if the register is greater than or equal to zero
|
Operation:
| if $s >= 0 PC +=offset << 2;
|
Syntax:
| bgez $s, offset
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000001 |
5ビット |
5'b00001 |
16ビット |
|
BGEZAL -- Branch on greater than or equal to zero and link
Description:
| Branches if the register is greater than or equal to zero and saves the
return address in $31
|
Operation:
| if $s >= 0 $31 = PC + 8 ; PC +=imm << 2;
|
Syntax:
| bgezal $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000001 |
5ビット |
5'h10001 |
16ビット |
|
BGTZ -- Branch on greater than zero
Description:
| Branches if the register is greater than zero
|
Operation:
| if $s > 0 PC +=imm << 2;
|
Syntax:
| bgtz $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000111 |
5ビット |
5'h0 |
16ビット |
|
BLEZ -- Branch on less than or equal to zero
Description:
| Branches if the register is less than or equal to zero
|
Operation:
| if $s <= 0 PC +=imm << 2;
|
Syntax:
| blez $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000110 |
5ビット |
5'h0 |
16ビット |
|
BLTZ -- Branch on less than zero
Description:
| Branches if the register is less than zero
|
Operation:
| if $s < 0 PC+=imm << 2;
|
Syntax:
| bltz $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b00001 |
5ビット |
5'b00000 |
16ビット |
|
BLTZAL -- Branch on less than zero and link
Description:
| Branches if the register is less than zero and saves the return address in
$31
|
Operation:
| if $s < 0 $31 = PC + 8 ; PC+=imm << 2;
|
Syntax:
| bltzal $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000001 |
5ビット |
5'b10000 |
16ビット |
|
BNE -- Branch on not equal
Description:
| Branches if the two registers are not equal
|
Operation:
| if $s != $t PC+=imm << 2;
|
Syntax:
| bne $s, $t, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b000101 |
5ビット |
5'h0 |
16ビット |
|
Break -- Break
Description:
| Generates break point.
|
Operation:
|
|
Syntax:
| break
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
????? |
????? |
????? |
????? |
6'b001101 |
|
DIV -- Divide
Description:
| Divides $s by $t and stores the quotient in $LO and the remainder in $HI
|
Operation:
| $LO = $s / $t; $HI = $s % $t;
|
Syntax:
| div $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5'h0 |
5'h0 |
6'b011010 |
|
DIVU -- Divide unsigned
Description:
| Divides $s by $t and stores the quotient in $LO and the remainder in $HI
|
Operation:
| $LO = $s / $t; $HI = $s % $t;
|
Syntax:
| divu $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5'h0 |
5'h0 |
6'b011011 |
|
J -- Jump
Description:
| Jumps to the calculated address
|
Operation:
| PC = nPC; nPC = (PC & 0xf0000000) | (imm26 << 2);
|
Syntax:
| j imm26
|
Encoding:
|
OPCODE |
Immediate |
6'b000010 |
26ビット |
|
JAL -- Jump and link
Description:
| Jumps to the calculated address and stores the return address in $31
|
Operation:
| $31 = PC + 8 ; PC = nPC; nPC = (PC & 0xf0000000) | (imm26 <<
2);
|
Syntax:
| jal imm26
|
Encoding:
|
OPCODE |
Immediate |
6'b000011 |
26ビット |
|
JALR -- Jump and link Register
Description:
| Jump to the address contained in register $s and stores the return address
in $d
|
Operation:
| $d = PC + 8 ; PC = $s
|
Syntax:
| jalr $d,$s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5'h0 |
5ビット |
5'h0 |
6'b001001 |
|
JR -- Jump register
Description:
| Jump to the address contained in register $s
|
Operation:
| PC = nPC; nPC = $s;
|
Syntax:
| jr $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5'h0 |
5'h0 |
5'h0 |
6'b001000 |
|
LB -- Load byte
Description:
| A signed extented byte is loaded into a register from the specified address.
|
Operation:
| $t = MEM[$s + imm]; ;
|
Syntax:
| lb $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b100000 |
5ビット |
5ビット |
16ビット |
|
LBU -- Load byte unsigned
Description:
| A unsigned extented byte is loaded into a register from the specified address.
|
Operation:
| $t = MEM[$s + imm]; ;
|
Syntax:
| lbu $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b100100 |
5ビット |
5ビット |
16ビット |
|
LH -- Load Half
Description:
| A signed extented half word is loaded into a register from the specified
address.
|
Operation:
| $t = MEM[$s + imm]; ;
|
Syntax:
| lh $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b100001 |
5ビット |
5ビット |
16ビット |
|
LHU -- Load Half unsigned
Description:
| A byte is loaded into a register from the specified address.
|
Operation:
| $t = MEM[$s + imm]; ;
|
Syntax:
| lhu $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b100101 |
5ビット |
5ビット |
16ビット |
|
LUI -- Load upper immediate
Description:
| The immediate value is shifted left 16 bits and stored in the register. The
lower 16 bits are zeroes.
|
Operation:
| $t = (imm << 16);
|
Syntax:
| lui $t, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001111 |
????? |
5ビット |
16ビット |
|
LW -- Load word
Description:
| A word is loaded into a register from the specified address.
|
Operation:
| $t = MEM[$s + imm];
|
Syntax:
| lw $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b100011 |
5ビット |
5ビット |
16ビット |
|
MFHI -- Move from HI
Description:
| The contents of register HI are moved to the specified register.
|
Operation:
| $d = $HI;
|
Syntax:
| mfhi $d
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5'h0 |
5'h0 |
5ビット |
5'h0 |
6'b010000 |
|
MFLO -- Move from LO
Description:
| The contents of register LO are moved to the specified register.
|
Operation:
| $d = $LO;
|
Syntax:
| mflo $d
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5'h0 |
5'h0 |
5ビット |
5'h0 |
6'b010010 |
|
MTHI -- Move to HI
Description:
| The contents of register $s are moved to $HI.
|
Operation:
| $HI=$s;
|
Syntax:
| mthi $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5'ビット |
5'h0 |
5'h0 |
5'h0 |
6'b010001 |
|
MTLO -- Move to LO
Description:
| The contents of register $s are moved to $HI.
|
Operation:
| $LO=$s;
|
Syntax:
| mtlo $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5'ビット |
5'h0 |
5'h0 |
5'h0 |
6'b010011 |
|
MULT -- Multiply
Description:
| Multiplies $s by $t and stores the result in $LO.
|
Operation:
| $LO = $s * $t;
|
Syntax:
| mult $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5'h0 |
5'h0 |
6'b011000 |
|
MULTU -- Multiply unsigned
Description:
| Multiplies $s by $t and stores the result in $LO.
|
Operation:
| $LO = $s * $t;
|
Syntax:
| multu $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5'h0 |
5'h0 |
6'b011001 |
|
NOR -- Bitwise nor
Description:
| Bitwise logical nors two registers and stores the result in a register
|
Operation:
| $d = ~($s | $t);
|
Syntax:
| nor $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100111 |
|
OR -- Bitwise or
Description:
| Bitwise logical ors two registers and stores the result in a register
|
Operation:
| $d = $s | $t;
|
Syntax:
| or $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100101 |
|
ORI -- Bitwise or immediate
Description:
| Bitwise ors a register and an immediate value and stores the result in a
register
|
Operation:
| $t = $s | imm;
|
Syntax:
| ori $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001101 |
5ビット |
5ビット |
16ビット |
|
SB -- Store byte
Description:
| The least significant byte of $t is stored at the specified address.
|
Operation:
| MEM[$s + imm] = (0xff & $t);
|
Syntax:
| sb $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b101000 |
5ビット |
5ビット |
16ビット |
|
SH -- Store Half
Description:
| The least significant half word of $t is stored at the specified address.
|
Operation:
| MEM[$s + imm] = (0xffff & $t);
|
Syntax:
| sh $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b101001 |
5ビット |
5ビット |
16ビット |
|
SLL -- Shift left logical
Description:
| Shifts a register value left by the shift amount listed in the instruction
and places the result in a third register. Zeroes are shifted in.
|
Operation:
| $d = $t << h;
|
Syntax:
| sll $d, $t, h
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
h |
6'b000000 |
|
SLLV -- Shift left logical variable
Description:
| Shifts a register value left by the value in a second register and places
the result in a third register. Zeroes are shifted in.
|
Operation:
| $d = $t << $s;
|
Syntax:
| sllv $d, $t, $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
????? |
6'b000100 |
|
SLT -- Set on less than (signed)
Description:
| If $s is less than $t, $d is set to one. It gets zero otherwise.
|
Operation:
| if $s < $t $d = 1; else $d = 0;
|
Syntax:
| slt $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b101010 |
|
SLTI -- Set on less than immediate (signed)
Description:
| If $s is less than immediate, $t is set to one. It gets zero otherwise.
|
Operation:
| if $s < imm $t = 1; else $t = 0;
|
Syntax:
| slti $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001010 |
5ビット |
5ビット |
16ビット |
|
SLTIU -- Set on less than immediate unsigned
Description:
| If $s is less than the unsigned immediate, $t is set to one. It gets zero
otherwise.
|
Operation:
| if $s < imm $t = 1; else $t = 0;
|
Syntax:
| sltiu $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001011 |
5ビット |
5ビット |
16ビット |
|
SLTU -- Set on less than unsigned
Description:
| If $s is less than $t, $d is set to one. It gets zero otherwise.
|
Operation:
| if $s < $t $d = 1; else $d = 0;
|
Syntax:
| sltu $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b101011 |
|
SRA -- Shift right arithmetic
Description:
| Shifts a register value right by the shift amount (shamt) and places the
value in the destination register. The sign bit is shifted in.
|
Operation:
| $d = $t >> h;
|
Syntax:
| sra $d, $t, h
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
h |
6'b000011 |
|
SRAV -- Shift right arithmatic variable
Description:
| Shifts a register value right by the value in a second register and places
the result in a third register. the sign bit is shifterd in.
|
Operation:
| $d = $t >> $s;
|
Syntax:
| srav $d, $t, $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
????? |
6'b000111 |
|
SRL -- Shift right logical
Description:
| Shifts a register value right by the shift amount (shamt) and places the
value in the destination register. Zeroes are shifted in.
|
Operation:
| $d = $t >> h;
|
Syntax:
| srl $d, $t, h
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
h |
6'b000010 |
|
SRLV -- Shift right logical variable
Description:
| Shifts a register value right by the amount specified in $s and places the
value in the destination register. Zeroes are shifted in.
|
Operation:
| $d = $t >> $s;
|
Syntax:
| srlv $d, $t, $s
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b000110 |
|
SUB -- Subtract
Description:
| Subtracts two registers and stores the result in a register(Overflowで例外発生)
|
Operation:
| $d = $s - $t;
|
Syntax:
| sub $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100010 |
|
SUBU -- Subtract unsigned
Description:
| Subtracts two registers and stores the result in a register
|
Operation:
| $d = $s - $t;
|
Syntax:
| subu $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
5'h0 |
6'b100011 |
|
SW -- Store word
Description:
| The contents of $t is stored at the specified address.
|
Operation:
| MEM[$s + imm] = $t;
|
Syntax:
| sw $t, imm($s)
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b101011 |
5ビット |
5ビット |
16ビット |
|
SYSCALL -- System call
Description:
| Generates a software interrupt.
|
Operation:
|
|
Syntax:
| syscall
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
????? |
????? |
????? |
????? |
6'b001100 |
|
XOR -- Bitwise exclusive or
Description:
| Exclusive ors two registers and stores the result in a register
|
Operation:
| $d = $s ^ $t;
|
Syntax:
| xor $d, $s, $t
|
Encoding:
|
OPCODE |
Source |
Target |
Destination |
Shift |
Function |
6’b000000 |
5ビット |
5ビット |
5ビット |
????? |
6'b100110 |
|
XORI -- Bitwise exclusive or immediate
Description:
| Bitwise exclusive ors a register and an immediate value and stores the
result in a register
|
Operation:
| $t = $s ^ imm;
|
Syntax:
| xori $t, $s, imm
|
Encoding:
|
OPCODE |
Source |
Target |
Immediate |
6'b001110 |
5ビット |
5ビット |
16ビット |
|