initial commit
This commit is contained in:
238
rtl/ip/open-la500/btb.v
Normal file
238
rtl/ip/open-la500/btb.v
Normal file
@@ -0,0 +1,238 @@
|
||||
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
|
||||
Reference in New Issue
Block a user