-
Notifications
You must be signed in to change notification settings - Fork 0
/
gshare.sv
125 lines (110 loc) · 3.74 KB
/
gshare.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
`timescale 1ns / 1ps
`include "riscv_core.svh"
/*
Very simple gshare with 1 bit counters, only to be used in fetch stage
Decode stage might use a more complicated version but idk
*/
module gshare #(
parameter HISTORY_WIDTH = 14
)(
input clk, reset,
branch_fb_ifc.in i_fb [2],
input [`ADDR_WIDTH-1:0] pred_addr [2],
input pred_addr_valid [2],
output riscv_pkg::BranchOutcome prediction[2],
output logic int_stall
);
logic [HISTORY_WIDTH-1:0] history;
logic [HISTORY_WIDTH-1:0] read_addr [2];
logic [HISTORY_WIDTH-1:0] write_addr [2];
assign read_addr[0] = history ^ pred_addr[0][HISTORY_WIDTH-1:0];
assign read_addr[1] = history ^ pred_addr[1][HISTORY_WIDTH-1:0];
assign write_addr[0] = history ^ i_fb[0].branch_pc[HISTORY_WIDTH-1:0];
assign write_addr[1] = history ^ i_fb[1].branch_pc[HISTORY_WIDTH-1:0];
logic [HISTORY_WIDTH-1:0] addr [2];
logic we [2];
logic din [2];
logic dout [2];
logic [1:0] write_sum, read_sum;
logic [2:0] port_sum;
always_comb begin
read_sum = pred_addr_valid[0] + pred_addr_valid[1];
write_sum = i_fb[0].if_branch + i_fb[1].if_branch;
port_sum = write_sum + read_sum;
if(port_sum > 2) begin
int_stall = 1;
end else begin
int_stall = 0;
end
end
always_ff @(posedge clk) begin
if(reset) begin
history <= 0;
end else begin
if(i_fb[0].if_branch) begin
if(i_fb[1].if_branch) begin
history <= {(history << 2), (i_fb[0].outcome == TAKEN), (i_fb[1].outcome == TAKEN)};
end else begin
history <= {(history << 1), (i_fb[0].outcome == TAKEN)};
end
end else if(i_fb[1].if_branch) begin
history <= {(history << 1), (i_fb[1].outcome == TAKEN)};
end
end
end
always_comb begin
we[0] = 0;
we[1] = 0;
din[0] = 0;
din[1] = 0;
if(i_fb[0].if_branch) begin
we[0] = 1;
din[0] = (i_fb[0].outcome == TAKEN) ? 1 : 0;
addr[0] = write_addr[0];
if(i_fb[1].if_branch) begin
we[1] = 1;
din[1] = (i_fb[1].outcome == TAKEN) ? 1 : 0;
addr[1] = write_addr[1];
end else if(pred_addr_valid[0]) begin
we[1] = 0;
din[1] = 0;
addr[1] = read_addr[0];
end else if(pred_addr_valid[1]) begin
we[1] = 0;
din[1] = 0;
addr[1] = read_addr[1];
end else begin
we[1] = 0;
din[1] = 0;
addr[1] = 0;
end
end else if (i_fb[1].if_branch) begin
we[0] = 1;
din[0] = (i_fb[1].outcome == TAKEN) ? 1 : 0;
addr[0] = write_addr[1];
if(pred_addr_valid[0]) begin
we[1] = 0;
din[1] = 0;
addr[1] = read_addr[0];
end else if(pred_addr_valid[1]) begin
we[1] = 0;
din[1] = 0;
addr[1] = read_addr[1];
end else begin
we[1] = 0;
din[1] = 0;
addr[1] = 0;
end
end else begin
we[0] = 0;
din[0] = 0;
addr[0] = read_addr[0];
we[0] = 0;
din[0] = 0;
addr[1] = read_addr[1];
end
end
bram_block #(.WIDTH(1), .DEPTH(1 << HISTORY_WIDTH)) HISTORY_TABLE(.*);
assign prediction[0] = (dout[0] == 0) ? NOT_TAKEN : TAKEN;
assign prediction[1] = (dout[1] == 0) ? NOT_TAKEN : TAKEN;
endmodule