From 1f1f61bbab1396278a861e46fd65a50d1914585e Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Sun, 9 Oct 2022 14:34:48 -0600 Subject: Pipeline flags writeback (breaks combinational data dependencies) --- rtl/core/psr.sv | 38 +++++++++++++++++++++++++++++++------- rtl/core/regs/regs.sv | 2 +- 2 files changed, 32 insertions(+), 8 deletions(-) (limited to 'rtl') 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; -- cgit v1.2.3