##<ID>
##
ここからIDステージ(<ID>
)。<IF>
でフェッチした命令に従い命令デコードをするほか、タグ生成を実行する。
###Tag Generator###
ソースはsrc/fpga/tag_generator.v。何のタグかというと、分岐投機実行タグである。"Modern Processor Design"の229ページから231ページにかけて、分岐の投機実行について書かれている。分岐予測の2つの側面があり、ひとつは分岐の投機実行と、他のひとつは分岐の妥当性検証及び修復である。分岐の投機実行は仮実行という印をタグに登録しておき、後で分岐予測の妥当性検証を実行する。その際に予測がはずれていれば、タグにより分岐を無効化する必要がある。これが修復と呼ばれるプロセスになる。
`include "constants.vh"
`default_nettype none
module tag_generator(
input wire clk,
input wire reset,
input wire branchvalid1,
input wire branchvalid2,
input wire prmiss,
input wire prsuccess,
input wire enable,
input wire [`SPECTAG_LEN-1:0] tagregfix,
output wire [`SPECTAG_LEN-1:0] sptag1,
output wire [`SPECTAG_LEN-1:0] sptag2,
output wire speculative1,
output wire speculative2,
output wire attachable,
output reg [`SPECTAG_LEN-1:0] tagreg
);
// reg [`SPECTAG_LEN-1:0] tagreg;
reg [`BRDEPTH_LEN-1:0] brdepth;
assign sptag1 = (branchvalid1) ?
{tagreg[`SPECTAG_LEN-2:0], tagreg[`SPECTAG_LEN-1]}
: tagreg;
inst1が有効な分岐命令であることを示すbranchvalid1がtrueのとき、5bitの分岐投機タグtagregを左へ1ビットローテートし、sptag1とする。
assign sptag2 = (branchvalid2) ?
{sptag1[`SPECTAG_LEN-2:0], sptag1[`SPECTAG_LEN-1]}
: sptag1;
inst2が有効な分岐命令であることを示すbranchvalid2がtrueのとき、5bitの分岐投機タグsptag1を左へ1ビットローテートし、sptag2とする。
assign speculative1 = (brdepth != 0) ? 1'b1 : 1'b0;
brdepth(投機分岐の深さ)が0で無い場合は、inst1が投機命令であることを示すspeculative1をtrueとする。
assign speculative2 = ((brdepth != 0) || branchvalid1) ? 1'b1 : 1'b0;
brdepth(投機分岐の深さ)が0で無いかまたはinst1が有効な分岐命令の場合は、inst2が投機命令であることを示すspeculative1をtrueとする。
assign attachable = (brdepth + branchvalid1 + branchvalid2)
> (`BRANCH_ENT_NUM + prsuccess) ? 1'b0 : 1'b1;
brdepth(投機分岐の深さ)と命令1及び命令2が分岐命令の場合の数を加えた数が、エントリ数を超えている場合は、
タグの割り当て可能を示す信号attachableをfalseとする。
always @ (posedge clk) begin
if (reset) begin
tagreg <= `SPECTAG_LEN'b1;
brdepth <= `BRDEPTH_LEN'b0;
end else begin
tagreg <= prmiss ? tagregfix :
~enable ? tagreg :
sptag2;
brdepth <= prmiss ? `BRDEPTH_LEN'b0 :
~enable ? brdepth - prsuccess :
brdepth + branchvalid1 + branchvalid2 - prsuccess;
end
end
endmodule // tag_generator
`default_nettype wire
クロック毎にtagregとbrdepthを更新する。更新のしかたは、tagregは、予測ミスの場合はtagregの修復値をロードし、そうでない場合は、イネーブルでない場合はtagregを、イネーブルの場合はsptag2をロードする。
分岐深さは、予測ミスの場合はゼロをロードし、そうでない場合は、イネーブルでない場合は分岐深さを
イネーブルの場合は分岐深さにbranchvalid1及びbranchvalid2を加えたものをロードする。