ISSの命令デコーダは、rubyから自動生成している。これを活用すると、ハードウェアのデコーダも自動生成できないだろうか。 とりあえず作ってみると、こんな感じになった。 まず、ISSのデコーダはRubyのテーブルで以下のように構成されている。
これのデコードテーブルの部分だけ取り出して、Xの入っていない部分(実際にデコードしなければならない部分)を取り出してみる。 Rubyで書いてみたのだが、以下のようにしてみた。 RISC-Vのデコードテーブルにがっつり依存しているので、記述としてはあまり良くないなあ。 ちょっと汎用化していきたい。
# generate instruction list $arch_table.each_with_index {|inst_info, index| is_generate_and = false mne = "INST_%s"%([inst_info[ARCH::NAME].split(" ")[0].gsub(/\./,'_').upcase]) mnemonic = " assign IF_INST_DEC[`" + mne + "] = " if not inst_info[ARCH::R3].include?("X") then mnemonic = mnemonic + "(IF_INST[31:27] == 5'b" mnemonic = mnemonic + inst_info[ARCH::R3] + ")" is_generate_and = true end if not inst_info[ARCH::F2].include?("X") then if is_generate_and == true then mnemonic = mnemonic + " & "; end mnemonic = mnemonic + "(IF_INST[26:25] == 2'b" mnemonic = mnemonic + inst_info[ARCH::F2] + ")" is_generate_and = true end if not inst_info[ARCH::R2].include?("X") then if is_generate_and == true then mnemonic = mnemonic + " & "; end mnemonic = mnemonic + "(IF_INST[24:20] == 5'b" mnemonic = mnemonic + inst_info[ARCH::R2] + ")" is_generate_and = true end if not inst_info[ARCH::R1].include?("X") then if is_generate_and == true then mnemonic = mnemonic + " & "; end mnemonic = mnemonic + "(IF_INST[19:15] == 5'b" mnemonic = mnemonic + inst_info[ARCH::R1] + ")" is_generate_and = true end ...
実際に生成されたVerilog-HDLファイルがこれだ。一応、Vivadoで合成してみて、エラーは発生していないようだ。
`default_nettype none `include "./riscv_dec.vh" module riscv_dec ( input wire [31: 0] IF_INST, output wire [136: 0] IF_INST_DEC ); assign IF_INST_DEC[`INST_LUI] = (IF_INST[ 6: 0] == 7'b0110111); assign IF_INST_DEC[`INST_AUIPC] = (IF_INST[ 6: 0] == 7'b0010111); assign IF_INST_DEC[`INST_JAL] = (IF_INST[ 6: 0] == 7'b1101111); assign IF_INST_DEC[`INST_JALR] = (IF_INST[14:12] == 3'b000) & (IF_INST[ 6: 0] == 7'b1100111); assign IF_INST_DEC[`INST_BEQ] = (IF_INST[14:12] == 3'b000) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_BNE] = (IF_INST[14:12] == 3'b001) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_BLT] = (IF_INST[14:12] == 3'b100) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_BGE] = (IF_INST[14:12] == 3'b101) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_BLTU] = (IF_INST[14:12] == 3'b110) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_BGEU] = (IF_INST[14:12] == 3'b111) & (IF_INST[ 6: 0] == 7'b1100011); assign IF_INST_DEC[`INST_LB] = (IF_INST[14:12] == 3'b000) & (IF_INST[ 6: 0] == 7'b0000011); assign IF_INST_DEC[`INST_LH] = (IF_INST[14:12] == 3'b001) & (IF_INST[ 6: 0] == 7'b0000011); assign IF_INST_DEC[`INST_LW] = (IF_INST[14:12] == 3'b010) & (IF_INST[ 6: 0] == 7'b0000011); assign IF_INST_DEC[`INST_LBU] = (IF_INST[14:12] == 3'b100) & (IF_INST[ 6: 0] == 7'b0000011); ...