239 lines
6.8 KiB
Verilog
239 lines
6.8 KiB
Verilog
module btb
|
|
#(
|
|
parameter BTBNUM = 32,
|
|
parameter RASNUM = 16
|
|
)
|
|
(
|
|
input clk ,
|
|
input reset ,
|
|
//from/to if
|
|
input [31:0] fetch_pc ,
|
|
input fetch_en ,
|
|
output [31:0] ret_pc ,
|
|
output taken ,
|
|
output ret_en ,
|
|
output [ 4:0] ret_index ,
|
|
//from id
|
|
input operate_en ,
|
|
input [31:0] operate_pc ,
|
|
input [ 4:0] operate_index ,
|
|
input pop_ras ,
|
|
input push_ras ,
|
|
input add_entry ,
|
|
input delete_entry ,
|
|
input pre_error ,
|
|
input pre_right ,
|
|
input target_error ,
|
|
input right_orien ,
|
|
input [31:0] right_target
|
|
);
|
|
|
|
/*
|
|
* btb_pc record all branch inst pc except jirl
|
|
* ras_pc only record jirl pc
|
|
*/
|
|
reg [29:0] btb_pc [BTBNUM-1:0];
|
|
reg [29:0] btb_target [BTBNUM-1:0];
|
|
reg [ 1:0] btb_counter [BTBNUM-1:0];
|
|
|
|
reg [BTBNUM-1:0] btb_valid;
|
|
|
|
reg [29:0] ras_pc [RASNUM-1:0];
|
|
|
|
reg [RASNUM-1:0] ras_valid;
|
|
|
|
reg [31:0] fetch_pc_r;
|
|
reg fetch_en_r;
|
|
|
|
//reg [BTBNUM-1:0] jirl_flag;
|
|
|
|
reg [29:0] ras [7:0];
|
|
reg [ 3:0] ras_ptr;
|
|
|
|
wire [29:0] ras_top;
|
|
|
|
wire ras_full;
|
|
wire ras_empty;
|
|
|
|
wire [31:0] btb_match_rd;
|
|
wire [15:0] ras_match_rd;
|
|
|
|
wire btb_match;
|
|
wire ras_match;
|
|
|
|
wire [29:0] btb_match_target;
|
|
wire [ 1:0] btb_match_counter;
|
|
wire [ 4:0] btb_match_index;
|
|
wire [ 4:0] btb_random_index;
|
|
|
|
wire [ 3:0] ras_match_index;
|
|
wire [ 3:0] ras_random_index;
|
|
|
|
wire btb_all_entry_valid;
|
|
wire [4:0] btb_select_one_invalid_entry;
|
|
wire [4:0] btb_add_entry_index;
|
|
reg [4:0] btb_add_entry_index_r;
|
|
wire [31:0] btb_add_entry_dec;
|
|
|
|
wire ras_all_entry_valid;
|
|
wire [3:0] ras_select_one_invalid_entry;
|
|
wire [3:0] ras_add_entry_index;
|
|
|
|
wire [31:0] btb_untaken_entry;
|
|
reg [31:0] btb_untaken_entry_r;
|
|
wire [31:0] btb_untaken_entry_t;
|
|
reg btb_add_entry_r;
|
|
wire [4:0] btb_sel_one_untaken_entry;
|
|
wire btb_has_one_untaken_entry;
|
|
|
|
reg [5:0] fcsr;
|
|
|
|
always @(posedge clk) begin
|
|
if (reset)
|
|
fetch_en_r <= 1'b0;
|
|
else
|
|
fetch_en_r <= fetch_en;
|
|
|
|
if (fetch_en)
|
|
fetch_pc_r <= fetch_pc;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
btb_untaken_entry_r <= btb_untaken_entry;
|
|
btb_add_entry_r <= operate_en && !pop_ras && add_entry;
|
|
btb_add_entry_index_r <= btb_add_entry_index;
|
|
end
|
|
|
|
//untaken entry list cal at previous clock
|
|
assign btb_untaken_entry_t = btb_untaken_entry_r & ({32{!btb_add_entry_r}} | ~btb_add_entry_dec);
|
|
assign btb_has_one_untaken_entry = |btb_untaken_entry_t;
|
|
|
|
decoder_5_32 dec_btb_add_entry (.in(btb_add_entry_index_r), .out(btb_add_entry_dec));
|
|
one_valid_32 sel_one_untaken_entry (.in(btb_untaken_entry_t), .out_en(btb_sel_one_untaken_entry));
|
|
|
|
//assign btb_random_index = (btb_match && (fcsr[4:0] == btb_match_index)) ? (fcsr[4:0]+1'b1) : fcsr[4:0];
|
|
//untaken entry can exit first, make no difference, except lose history infor.
|
|
assign btb_add_entry_index = !btb_all_entry_valid ? btb_select_one_invalid_entry :
|
|
btb_has_one_untaken_entry ? btb_sel_one_untaken_entry :
|
|
fcsr[4:0] ;
|
|
|
|
assign btb_all_entry_valid = &btb_valid;
|
|
one_valid_32 sel_one_btb_entry (.in(~btb_valid), .out_en(btb_select_one_invalid_entry));
|
|
|
|
//assign ras_random_index = (ras_match && (fcsr[3:0] == ras_match_index)) ? (fcsr[3:0]+1'b1) : fcsr[3:0];
|
|
assign ras_add_entry_index = ras_all_entry_valid ? fcsr[3:0] : ras_select_one_invalid_entry;
|
|
assign ras_all_entry_valid = &ras_valid;
|
|
one_valid_16 sel_one_ras_entry (.in(~ras_valid), .out_en(ras_select_one_invalid_entry));
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
btb_valid <= 32'b0;
|
|
ras_valid <= 16'b0;
|
|
end
|
|
else if (operate_en && !pop_ras) begin
|
|
if (add_entry) begin
|
|
btb_valid[btb_add_entry_index] <= 1'b1;
|
|
btb_pc[btb_add_entry_index] <= operate_pc[31:2];
|
|
btb_target[btb_add_entry_index] <= right_target[31:2];
|
|
btb_counter[btb_add_entry_index] <= 2'b10;
|
|
end
|
|
else if (target_error) begin
|
|
btb_target[operate_index] <= right_target[31:2];
|
|
btb_counter[operate_index] <= 2'b10;
|
|
end
|
|
else if (pre_error || pre_right) begin
|
|
if (right_orien) begin
|
|
if (btb_counter[operate_index] != 2'b11) begin
|
|
btb_counter[operate_index] <= btb_counter[operate_index] + 2'b1;
|
|
end
|
|
end
|
|
else begin
|
|
if (btb_counter[operate_index] != 2'b00) begin
|
|
btb_counter[operate_index] <= btb_counter[operate_index] - 2'b1;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
else if (operate_en && pop_ras) begin
|
|
if (add_entry) begin
|
|
ras_valid[ras_add_entry_index] <= 1'b1;
|
|
ras_pc[ras_add_entry_index] <= operate_pc[31:2];
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < BTBNUM; i = i + 1)
|
|
begin: btb_match_com
|
|
assign btb_match_rd[i] = fetch_en_r && ((fetch_pc_r[31:2] == btb_pc[i]) && btb_valid[i]);
|
|
end
|
|
endgenerate
|
|
|
|
generate
|
|
for (i = 0; i < RASNUM; i = i + 1)
|
|
begin: ras_match_com
|
|
assign ras_match_rd[i] = fetch_en_r && ((fetch_pc_r[31:2] == ras_pc[i]) && ras_valid[i]);
|
|
end
|
|
endgenerate
|
|
|
|
generate
|
|
for (i = 0; i < BTBNUM; i = i + 1)
|
|
begin: sel_untaken_entry
|
|
assign btb_untaken_entry[i] = btb_valid[i] && ~|btb_counter[i];
|
|
end
|
|
endgenerate
|
|
|
|
assign btb_match = |btb_match_rd;
|
|
assign ras_match = |ras_match_rd && !ras_empty;
|
|
|
|
assign ras_top = ras[ras_ptr - 4'b1]; //ras modify may before inst fetch
|
|
|
|
encoder_32_5 encode_btb_match (.in(btb_match_rd), .out(btb_match_index));
|
|
encoder_16_4 encode_ras_match (.in(ras_match_rd), .out(ras_match_index));
|
|
|
|
assign btb_match_target = btb_target[btb_match_index];
|
|
assign btb_match_counter = btb_counter[btb_match_index];
|
|
|
|
assign ret_pc = {32{ras_match}} & {ras_top, 2'b0} |
|
|
{32{btb_match}} & {btb_match_target, 2'b0};
|
|
assign ret_en = btb_match || ras_match;
|
|
assign taken = btb_match && btb_match_counter[1] || ras_match;
|
|
assign ret_index = {5{btb_match}} & {btb_match_index} |
|
|
{5{ras_match}} & {1'b0,ras_match_index};
|
|
|
|
assign ras_full = ras_ptr[3];
|
|
assign ras_empty = (ras_ptr == 4'd0);
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
ras_ptr <= 4'b0;
|
|
end
|
|
else if (operate_en) begin
|
|
if (push_ras && !ras_full) begin
|
|
ras[ras_ptr] <= operate_pc[31:2] + 30'b1;
|
|
ras_ptr <= ras_ptr + 4'b1;
|
|
end
|
|
else if (pop_ras && !ras_empty) begin
|
|
ras_ptr <= ras_ptr - 4'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
fcsr <= 6'b100010;
|
|
end
|
|
else begin
|
|
fcsr[0] <= fcsr[5];
|
|
fcsr[1] <= fcsr[0];
|
|
fcsr[2] <= fcsr[1];
|
|
fcsr[3] <= fcsr[2] ^ fcsr[5];
|
|
fcsr[4] <= fcsr[3] ^ fcsr[5];
|
|
fcsr[5] <= fcsr[4];
|
|
end
|
|
end
|
|
|
|
endmodule
|