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
|
`include "gfx/gfx_defs.sv"
module gfx_sp_issue
(
input logic clk,
rst_n,
input insn_deco deco,
input logic deco_valid,
output logic deco_ready,
output vreg_num rd_a_reg,
rd_b_reg,
input logic stream_issue_ready,
output logic stream_issue_valid,
input logic combiner_issue_ready,
output logic combiner_issue_valid,
input logic shuffler_issue_ready,
output logic shuffler_issue_valid,
input logic wr,
input vreg_num wr_reg
);
/* Esto podría ser fully pipelined, pero no dio tiempo, y en
* todo caso no haría diferencia debido al pésimo ancho de banda.
*/
logic data_hazard, rd_a_hazard, rd_b_hazard, wr_hazard, writing_a, writing_b, writing_dst,
busy[`GFX_SP_REG_COUNT];
enum int unsigned
{
IDLE,
HAZARDS,
ISSUE,
WAIT
} state;
assign rd_a_reg = deco.src_a;
assign rd_b_reg = deco.src_b;
assign wr_hazard = deco.writeback && writing_dst;
assign rd_a_hazard = deco.read_src_a && writing_a;
assign rd_b_hazard = deco.read_src_a && writing_b;
assign data_hazard = rd_a_hazard || rd_b_hazard || wr_hazard;
assign deco_ready = (stream_issue_ready && stream_issue_valid)
|| (combiner_issue_ready && combiner_issue_valid)
|| (shuffler_issue_ready && shuffler_issue_valid);
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) begin
state <= IDLE;
stream_issue_valid <= 0;
combiner_issue_valid <= 0;
shuffler_issue_valid <= 0;
for (integer i = 0; i < `GFX_SP_REG_COUNT; ++i)
busy[i] <= 0;
end else begin
unique case (state)
IDLE:
if (deco_valid)
state <= HAZARDS;
HAZARDS:
if (!data_hazard) begin
state <= ISSUE;
if (deco.writeback)
busy[deco.dst] <= 1;
end
ISSUE: begin
state <= WAIT;
if (deco.ex.stream)
stream_issue_valid <= 1;
if (deco.ex.combiner)
combiner_issue_valid <= 1;
if (deco.ex.shuffler)
shuffler_issue_valid <= 1;
end
WAIT:
if (deco_ready) begin
state <= IDLE;
stream_issue_valid <= 0;
combiner_issue_valid <= 0;
shuffler_issue_valid <= 0;
end
endcase
if (wr)
busy[wr_reg] <= 0;
end
always_ff @(posedge clk) begin
writing_a <= busy[deco.src_a];
writing_b <= busy[deco.src_b];
writing_dst <= busy[deco.dst];
end
endmodule
|