summaryrefslogtreecommitdiff
path: root/rtl/core
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-10-09 14:34:48 -0600
committerAlejandro Soto <alejandro@34project.org>2022-10-09 14:34:48 -0600
commit1f1f61bbab1396278a861e46fd65a50d1914585e (patch)
treeb8ba06e3f891cc42b6bf73abbd58fd33e7898b7b /rtl/core
parent4ea1cd32da476616c66799d210913b001772a1e2 (diff)
Pipeline flags writeback (breaks combinational data dependencies)
Diffstat (limited to 'rtl/core')
-rw-r--r--rtl/core/psr.sv38
-rw-r--r--rtl/core/regs/regs.sv2
2 files changed, 32 insertions, 8 deletions
diff --git a/rtl/core/psr.sv b/rtl/core/psr.sv
index 30bb320..ee672e1 100644
--- a/rtl/core/psr.sv
+++ b/rtl/core/psr.sv
@@ -10,21 +10,45 @@ module core_psr
output psr_flags flags
);
- psr_flags cpsr_flags;
+ /* Este diseño de doble búfer es importante por rendimiento. Reducirlo
+ * a uno más "sencillo" tiene un costo de casi 40MHz menos en Fmax.
+ * Esto se debe a que el CPSR es el mayor mercado del core, se encuentra
+ * conectado a cycles, regs, alu y decode. La dependencia con decode en
+ * particular es crítica debido a que el condition code se especifica en
+ * términos de banderas de CPSR. Una ruta combinacional que atraviese flags
+ * iniciaría en cycles, tomaría valores de regs, llegaría a ALU, caería
+ * en flags y, debido al operand forwarding que se necesita por hazards de
+ * pipeline, esa misma señal seguiría combinacionalmente hacia decode para
+ * finalmente registrar en cycles nuevamente. Tal cosa es impermisible.
+ */
+
+ psr_flags cpsr_flags, next_flags, wr_flags;
+ logic pending_update;
+
+ assign flags = pending_update ? wr_flags : cpsr_flags;
always_comb begin
- flags = cpsr_flags;
+ next_flags = flags;
if(update_flags) begin
- flags = alu_flags;
+ next_flags = alu_flags;
if(~alu_v_valid)
- flags.v = cpsr_flags.v;
+ next_flags.v = flags.v;
end
end
- always_ff @(posedge clk)
- cpsr_flags <= flags;
+ always_ff @(posedge clk) begin
+ wr_flags <= next_flags;
+ if(pending_update)
+ cpsr_flags <= flags;
- initial cpsr_flags = 4'b0000;
+ pending_update <= update_flags;
+ end
+
+ initial begin
+ flags = 4'b0000;
+ cpsr_flags = 4'b0000;
+ pending_update = 0;
+ end
endmodule
diff --git a/rtl/core/regs/regs.sv b/rtl/core/regs/regs.sv
index 6ddf335..9b9ba57 100644
--- a/rtl/core/regs/regs.sv
+++ b/rtl/core/regs/regs.sv
@@ -29,7 +29,7 @@ module core_regs
assign pc_word = {pc_visible, 2'b00};
assign rd_value_a = rd_pc_a ? pc_word : (wr_enable && rd_index_a == wr_index) ? wr_value : file_rd_value_a;
- assign rd_value_b = rd_pc_b ? pc_word : (wr_enable && rd_index_a == wr_index) ? wr_value : file_rd_value_b;
+ assign rd_value_b = rd_pc_b ? pc_word : (wr_enable && rd_index_b == wr_index) ? wr_value : file_rd_value_b;
assign file_wr_enable = wr_enable & ~wr_pc;
assign branch = wr_enable & wr_pc;