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
|
`include "core/uarch.sv"
module core_psr
(
input logic clk,
update_flags,
alu_v_valid,
input psr_flags alu_flags,
output psr_flags 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
next_flags = flags;
if(update_flags) begin
next_flags = alu_flags;
if(~alu_v_valid)
next_flags.v = flags.v;
end
end
always_ff @(posedge clk) begin
wr_flags <= next_flags;
if(pending_update)
cpsr_flags <= flags;
pending_update <= update_flags;
end
initial begin
flags = 4'b0000;
cpsr_flags = 4'b0000;
pending_update = 0;
end
endmodule
|