summaryrefslogtreecommitdiff
path: root/rtl/gfx/gfx_sp_issue.sv
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/gfx/gfx_sp_issue.sv')
-rw-r--r--rtl/gfx/gfx_sp_issue.sv111
1 files changed, 111 insertions, 0 deletions
diff --git a/rtl/gfx/gfx_sp_issue.sv b/rtl/gfx/gfx_sp_issue.sv
new file mode 100644
index 0000000..6934e39
--- /dev/null
+++ b/rtl/gfx/gfx_sp_issue.sv
@@ -0,0 +1,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