Espressoを用いたデコードラッパを作っているが、もう少し便利にしたい。制御信号の生成については、TrueかFalseしか指定することができなかった。
"inst_ctrl":["RD_R3", "OP_SIGN_ADD", "IMM_U"]
しかし、この制御信号の意味は実際にはRD
制御信号がR3
であるという意味なので、もう少し細かく制御ができるようにしたい。
目標としては、以下のようなJSONファイルが扱えるようになりたい。
[ { "name":"lui r[11:7],h[31:12]", "inst_ctrl":[["cat", "arith"], ["rd","r3"], ["op", "sign_lui"], ["imm", "u"]] }, { "name":"auipc r[11:7],h[31:12]", "inst_ctrl":[["cat", "arith"], ["r1", "pc"], ["rd","r3"], ["op", "sign_auipc"], ["imm", "u"]] }, { "name":"add r[11:7],r[19:15],r[24:20]", "inst_ctrl":[["cat", "arith"], ["rd","r3"], ["r1", "r1"], ["r2", "r2"], ["op", "sign_add"] ] }, { "name":"sub r[11:7],r[19:15],r[24:20]", "inst_ctrl":[["cat", "arith"], ["rd","r3"], ["r1", "r1"], ["r2", "r2"], ["op", "sign_sub"] ] }, { "name":"ld r[11:7],h[31:20](r[19:15])", "inst_ctrl":[["cat", "mem"], ["rd","r3"], ["r1", "r1"], ["r2", "r2"], ["size", "dw"], ["sign", "s"]] }, { "name":"sd r[24:20],h[31:25]|h[11:7](r[19:15])", "inst_ctrl":[["cat", "mem"], ["r1", "r1"], ["r2", "r2"], ["size", "dw"], ["sign", "s"]] } ]
例えば、op
のフィールドについてはsign_lui
, sign_auipc
, sign_add
, sign_sub
の4種類のフィールドが取れるようにするべきだ。このように改造する。最終的には、これらのフィールド値についてもSystemVerilogでテンプレートを生成できるようにしておきたいものだが。
とりあえず、適当にRubyでこれらの値を読み込んでリストを作り上げるスクリプトを組んで、Espressoに読み込むべき以下のファイルが生成できるようになった。
type fd .i 32 .o 9 .ilb inst[0] inst[1] inst[2] inst[3] inst[4] inst[5] inst[6] inst[7] inst[8] inst[9] inst[10] inst[11] inst[12] inst[13] inst[14] inst[15] inst[16] inst[17] inst[18] inst[19] inst[20] inst[21] inst[22] inst[23] inst[24] inst[25] inst[26] inst[27] inst[28] inst[29] inst[30] inst[31] .ob cat[0] rd op[1] op[0] imm r1[0] r2 size sign -------------------------0110111 000000000 -------------------------0010111 000100000 0000000----------000-----0110011 001001000 0100000----------000-----0110011 001101000 -----------------011-----0000011 100001000 -----------------011-----0100011 100001000 .e
これを読み込んで、最終的に以下のようなSystemVerilogファイルが生成できるようになった。
module decoder ( input logic [31:0] inst, output logic cat, output logic rd, output logic [1: 0] op, output logic imm, output logic r1, output logic r2, output logic size, output logic sign ); wire tmp_0 = !inst[31] & inst[30] & !inst[29] & !inst[28] & !inst[27] & !inst[26] & !inst[25] & !inst[14] & !inst[13] & !inst[12] & !inst[6] & inst[5] & inst[4] & !inst[3] & !inst[2] & inst[1] & inst[0] & 1'b1; wire tmp_1 = !inst[31] & !inst[29] & !inst[28] & !inst[27] & !inst[26] & !inst[25] & !inst[14] & !inst[13] & !inst[12] & !inst[6] & inst[5] & inst[4] & !inst[3] & !inst[2] & inst[1] & inst[0] & 1'b1; wire tmp_2 = !inst[14] & inst[13] & inst[12] & !inst[6] & !inst[4] & !inst[3] & !inst[2] & inst[1] & inst[0] & 1'b1; wire tmp_3 = !inst[6] & !inst[5] & inst[4] & !inst[3] & inst[2] & inst[1] & inst[0] & 1'b1; assign cat = tmp_2 | 1'b0; assign rd = 1'b0; assign op[1] = tmp_1 | 1'b0; assign op[0] = tmp_0 | tmp_3 | 1'b0; assign imm = 1'b0; assign r1 = tmp_1 | tmp_2 | 1'b0; assign r2 = 1'b0; assign size = 1'b0; assign sign = 1'b0; endmodule
なんとなく上手く行っているような気がしている。