自作RISC-Vアウトオブオーダコアの実装、FPUを実装している。FPUの基本的な算術演算はFPNewにより動作するようになったが、算術演算以外の命令はまだサポートしていない。調査してみよう。
FPNewはいくつかのサブモジュールから構成されているが、基本的な演算をサポートしているのがfpnew_fma
というモジュールだ。これにより加減算・乗算を実行する。
fpnew_fma #( .FpFormat (fpnew_pkg::FP64), .NumPipeRegs(1), .PipeConfig (fpnew_pkg::BEFORE), .TagType (logic), .AuxType (logic) ) fpnew_64 ( .clk_i (i_clk ), .rst_ni (i_reset_n), // Input signals .operands_i (w_fma64_rs ), // input logic [2:0][WIDTH-1:0] // 3 operands .is_boxed_i (w_fma64_boxed ), // input logic [2:0] // 3 operands .rnd_mode_i (fpnew_pkg::RNE ), // input fpnew_pkg::roundmode_e .op_i (w_fpnew_op ), // input fpnew_pkg::operation_e .op_mod_i (w_fpnew_op_mod ), // input logic .tag_i (1'b0 ), // input TagType .aux_i (1'b0 ), // input AuxType // Input Handshake .in_valid_i (w_fma64_in_valid ), // input logic .in_ready_o (o_ready ), // output logic .flush_i (1'b0 ), // input logic // Output signals .result_o (w_fma64_result ), // output logic [WIDTH-1:0] .status_o (w_fma64_fflags ), // output fpnew_pkg::status_t .extension_bit_o ( ), // output logic .tag_o ( ), // output TagType .aux_o ( ), // output AuxType // Output handshake .out_valid_o (w_fma64_out_valid), // output logic .out_ready_i (1'b1 ), // input logic // Indication of valid data in flight .busy_o ( ) // output logic );
一方でそれ以外のFCLASS命令や比較命令はfpnew_noncomp
というモジュールを使って実行するようだ。
fpnew_noncomp #( .FpFormat (fpnew_pkg::FP64), .NumPipeRegs(1), .PipeConfig (fpnew_pkg::BEFORE), .TagType (logic), .AuxType (logic) ) fpnew_noncomp64 ( .clk_i (i_clk ), .rst_ni (i_reset_n), .operands_i ( w_noncomp64_rs ), .is_boxed_i ( w_noncomp64_boxed ), .rnd_mode_i ( i_pipe_ctrl.op == OP_FEQ ? fpnew_pkg::RDN : i_pipe_ctrl.op == OP_FLT ? fpnew_pkg::RTZ : i_pipe_ctrl.op == OP_FLE ? fpnew_pkg::RNE : .op_i ( w_fpnew_op ), .op_mod_i ( w_fpnew_op_mod ), .tag_i ( 1'b0 ), .aux_i ( ), // Remember whether operation was vectorial .in_valid_i ( w_noncomp64_in_valid ), .in_ready_o ( ), .flush_i ( 1'b0 ), .result_o ( w_noncomp64_result ), .status_o ( w_noncomp64_status ), .extension_bit_o ( ), .class_mask_o ( w_noncomp64_class_mask ), .is_class_o ( ), .tag_o ( ), .aux_o ( ), .out_valid_o ( w_noncomp64_out_valid ), .out_ready_i ( 1'b1 ), .busy_o ( ) );
まずはfclass
のテストを実行してみると、正しく結果を取得できた。ちなみにFCLASSの値はFPNewは以下のenum
でサポートされており、そのまま整数に変換するだけで汎用レジスタに格納することができる。
// Classification mask typedef enum logic [9:0] { NEGINF = 10'b00_0000_0001, NEGNORM = 10'b00_0000_0010, NEGSUBNORM = 10'b00_0000_0100, NEGZERO = 10'b00_0000_1000, POSZERO = 10'b00_0001_0000, POSSUBNORM = 10'b00_0010_0000, POSNORM = 10'b00_0100_0000, POSINF = 10'b00_1000_0000, SNAN = 10'b01_0000_0000, QNAN = 10'b10_0000_0000 } classmask_e;
さらに少し注意して、比較演算のときは比較の種類によって少しフラグを少し使い分ける必要がある。
これにより、FCLASS命令と比較命令が動作するようになった。