Skip to content

Commit 880a272

Browse files
committed
feat(hwstack): add automatic register saving
Implementation without duplicated register file state.
1 parent 4e87b43 commit 880a272

10 files changed

Lines changed: 266 additions & 8 deletions

core/ariane_regfile_ff.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ module ariane_regfile #(
3636
// read port
3737
input logic [ NR_READ_PORTS-1:0][ 4:0] raddr_i,
3838
output logic [ NR_READ_PORTS-1:0][DATA_WIDTH-1:0] rdata_o,
39+
output logic [ 31:0][DATA_WIDTH-1:0] regs_o,
3940
// write port
4041
input logic [CVA6Cfg.NrCommitPorts-1:0][ 4:0] waddr_i,
4142
input logic [CVA6Cfg.NrCommitPorts-1:0][DATA_WIDTH-1:0] wdata_i,
@@ -48,6 +49,9 @@ module ariane_regfile #(
4849
logic [ NUM_WORDS-1:0][DATA_WIDTH-1:0] mem;
4950
logic [CVA6Cfg.NrCommitPorts-1:0][ NUM_WORDS-1:0] we_dec;
5051

52+
for (genvar i = 0; i < 32; i++) begin
53+
assign regs_o[i] = mem[i];
54+
end
5155

5256
always_comb begin : we_decoder
5357
for (int unsigned j = 0; j < CVA6Cfg.NrCommitPorts; j++) begin

core/commit_stage.sv

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ module commit_stage
9797
// TO_BE_COMPLETED - CONTROLLER
9898
output logic hfence_gvma_o,
9999
// Breakpoint exception from trigger module
100-
input logic break_from_trigger_i
100+
input logic break_from_trigger_i,
101+
// Hardware stacking registers count - CONTROLLER
102+
input logic [4:0] hwstack_regs_count_i
101103
);
102104

103105
// ila_0 i_ila_commit (
@@ -145,6 +147,8 @@ module commit_stage
145147

146148
assign commit_tran_id_o = commit_instr_int[0].trans_id;
147149

150+
logic [CVA6Cfg.NrCommitPorts-1:0] commit_stall;
151+
148152
logic instr_0_is_amo;
149153
logic [CVA6Cfg.NrCommitPorts-1:0] commit_macro_ack;
150154
assign instr_0_is_amo = is_amo(commit_instr_int[0].op);
@@ -157,6 +161,8 @@ module commit_stage
157161
commit_ack_o[0] = 1'b0;
158162
commit_macro_ack[0] = 1'b0;
159163

164+
commit_stall = '0;
165+
160166
amo_valid_commit_o = 1'b0;
161167

162168
we_gpr_o[0] = 1'b0;
@@ -331,6 +337,12 @@ module commit_stage
331337
amo_valid_commit_o = 1'b1;
332338
we_gpr_o[0] = amo_resp_i.ack;
333339
end
340+
// Stall commit if the instruction would overwrite a register which is being saved on the stack
341+
if (we_gpr_o[0] && |(waddr_o[0]) && (waddr_o[0] <= hwstack_regs_count_i)) begin
342+
commit_stall[0] = 1'b1;
343+
commit_ack_o[0] = 1'b0;
344+
we_gpr_o[0] = 1'b0;
345+
end
334346
end
335347
end
336348

@@ -382,6 +394,12 @@ module commit_stage
382394
end
383395
end
384396
end
397+
// Stall commit if the instruction would overwrite a register which is being saved on the stack
398+
if (we_gpr_o[1] && |(waddr_o[1]) && (waddr_o[1] <= hwstack_regs_count_i)) begin
399+
commit_stall[1] = 1'b1;
400+
commit_ack_o[1] = 1'b0;
401+
we_gpr_o[1] = 1'b0;
402+
end
385403
end
386404
end
387405
if (CVA6Cfg.RVZCMP) begin

core/controller.sv

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ module controller
1919
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
2020
parameter type bp_resolve_t = logic,
2121
parameter type icache_dreq_t = logic,
22-
parameter type icache_drsp_t = logic
22+
parameter type icache_drsp_t = logic,
23+
parameter type dcache_req_i_t = logic,
24+
parameter type dcache_req_o_t = logic
2325
) (
2426
// Subsystem Clock - SUBSYSTEM
2527
input logic clk_i,
@@ -67,6 +69,8 @@ module controller
6769
output logic halt_frontend_o,
6870
// Halt signal to commit stage - COMMIT_STAGE
6971
output logic halt_o,
72+
// Hardware stacking counter - COMMIT_STAGE
73+
output logic [4:0] hwstack_regs_count_o,
7074
// Cache is busy - CACHE
7175
input logic cache_busy_i,
7276
// Let dcache not accept any new requests - CACHE
@@ -87,10 +91,22 @@ module controller
8791
input logic eret_i,
8892
// We got an exception, flush the pipeline - FRONTEND
8993
input logic ex_valid_i,
94+
// Exception is CLIC interrupt - CSR_REGFILE
95+
input logic clic_irq_i,
9096
// Exception is CLIC vectored interrupt - CSR_REGFILE
9197
input logic clic_vec_irq_i,
98+
// Trap frame base address - CSR
99+
input logic [CVA6Cfg.VLEN-1:0] trap_frame_base_i,
92100
// Address of trap vector table entry - CSR
93101
input logic [CVA6Cfg.VLEN-1:0] trap_vector_base_i,
102+
// Integer Register File content - ISSUE_STAGE
103+
input logic [31:0] [CVA6Cfg.XLEN-1:0] int_regs_i,
104+
// Floating Point Register File content - ISSUE_STAGE
105+
input logic [31:0] [CVA6Cfg.XLEN-1:0] fp_regs_i,
106+
// Page offset for address aliasing checks - EX_STAGE
107+
input logic [11:0] page_offset_i,
108+
// Page offset matches - EX_STAGE
109+
output logic page_offset_matches_o,
94110
// Set PC - FRONTEND
95111
output logic frontend_set_pc_o,
96112
// PC to be set - FRONTEND
@@ -99,6 +115,10 @@ module controller
99115
output icache_dreq_t icache_dreq_o,
100116
// Handshake between CACHE and CONTROLLER (vectored irq handler address fetch) - CACHES
101117
input icache_drsp_t icache_drsp_i,
118+
// Data cache request - CACHES
119+
output dcache_req_i_t dcache_req_o,
120+
// Data cache response - CACHES
121+
input dcache_req_o_t dcache_rsp_i,
102122
// set the debug pc from CSR - FRONTEND
103123
input logic set_debug_pc_i,
104124
// We got a resolved branch, check if we need to flush the front-end - EX_STAGE
@@ -231,6 +251,109 @@ module controller
231251
endcase
232252
end
233253

254+
// Hardware stacking FSM
255+
typedef enum logic [1:0] {
256+
HWSTACK_IDLE,
257+
HWSTACK_SEND_REQ,
258+
HWSTACK_WAIT_GNT
259+
} hwstack_state_e;
260+
261+
hwstack_state_e hwstack_state_d, hwstack_state_q;
262+
logic hwstack_dcache_req_valid, hwstack_dcache_tag_valid;
263+
logic [4:0] hwstack_regs_count_d, hwstack_regs_count_q;
264+
logic [CVA6Cfg.VLEN-1:0] hwstack_dcache_address;
265+
logic [CVA6Cfg.XLEN-1:0] hwstack_dcache_wdata;
266+
267+
assign dcache_req_o.data_req = hwstack_dcache_req_valid;
268+
assign dcache_req_o.tag_valid = hwstack_dcache_tag_valid;
269+
assign dcache_req_o.address_index = hwstack_dcache_address[CVA6Cfg.DCACHE_INDEX_WIDTH-1:0];
270+
assign dcache_req_o.address_tag = hwstack_dcache_address[CVA6Cfg.DCACHE_TAG_WIDTH+CVA6Cfg.DCACHE_INDEX_WIDTH-1:CVA6Cfg.DCACHE_INDEX_WIDTH];
271+
assign dcache_req_o.data_wdata = hwstack_dcache_wdata;
272+
assign dcache_req_o.data_wuser = '0;
273+
assign dcache_req_o.data_we = 1'b1;
274+
assign dcache_req_o.data_be = '1;
275+
assign dcache_req_o.data_size = '1;
276+
assign dcache_req_o.data_id = '0;
277+
assign dcache_req_o.kill_req = '0;
278+
assign dcache_req_o.cbo_op = '0;
279+
280+
assign hwstack_regs_count_o = (hwstack_state_q != HWSTACK_IDLE) ? hwstack_regs_count_q : '0;
281+
282+
always_ff @(posedge clk_i or negedge rst_ni) begin
283+
if (~rst_ni) begin
284+
hwstack_state_q <= HWSTACK_IDLE;
285+
hwstack_regs_count_q <= '0;
286+
end else begin
287+
hwstack_state_q <= hwstack_state_d;
288+
hwstack_regs_count_q <= hwstack_regs_count_d;
289+
end
290+
end
291+
292+
always_comb begin : hwstack_load_offset_check
293+
page_offset_matches_o = 1'b0;
294+
if (hwstack_state_q != HWSTACK_IDLE) begin
295+
if ((page_offset_i >= trap_frame_base_i[11:0]) && (page_offset_i < hwstack_dcache_address[11:0])) begin
296+
page_offset_matches_o = 1'b1;
297+
end
298+
end
299+
end
300+
301+
always_comb begin : hwstack_logic
302+
// Default assignments
303+
hwstack_state_d = hwstack_state_q;
304+
hwstack_regs_count_d = hwstack_regs_count_q;
305+
hwstack_dcache_address = trap_frame_base_i + (hwstack_regs_count_q << 3);
306+
hwstack_dcache_wdata = int_regs_i[hwstack_regs_count_q];
307+
hwstack_dcache_req_valid = 1'b0;
308+
hwstack_dcache_tag_valid = 1'b0;
309+
unique case (hwstack_state_q)
310+
311+
HWSTACK_IDLE: begin
312+
hwstack_regs_count_d = 'd31;
313+
if (ex_valid_i && clic_irq_i) begin
314+
hwstack_dcache_req_valid = 1'b1;
315+
hwstack_dcache_wdata = int_regs_i[hwstack_regs_count_d];
316+
if (dcache_rsp_i.data_gnt) begin
317+
hwstack_state_d = HWSTACK_SEND_REQ;
318+
end else begin
319+
hwstack_state_d = HWSTACK_WAIT_GNT;
320+
end
321+
end
322+
end
323+
324+
HWSTACK_SEND_REQ: begin
325+
hwstack_dcache_req_valid = 1'b1;
326+
if (dcache_rsp_i.data_gnt) begin
327+
if (hwstack_regs_count_q == '0) begin
328+
hwstack_state_d = HWSTACK_IDLE;
329+
end else begin
330+
hwstack_regs_count_d = hwstack_regs_count_q - 1;
331+
hwstack_state_d = HWSTACK_SEND_REQ;
332+
end
333+
end else begin
334+
hwstack_state_d = HWSTACK_WAIT_GNT;
335+
end
336+
end
337+
338+
HWSTACK_WAIT_GNT: begin
339+
hwstack_dcache_req_valid = 1'b1;
340+
if (dcache_rsp_i.data_gnt) begin
341+
if (hwstack_regs_count_q == '0) begin
342+
hwstack_state_d = HWSTACK_IDLE;
343+
end else begin
344+
hwstack_regs_count_d = hwstack_regs_count_q - 1;
345+
hwstack_state_d = HWSTACK_SEND_REQ;
346+
end
347+
end
348+
end
349+
350+
default: begin
351+
hwstack_state_d = HWSTACK_IDLE;
352+
end
353+
354+
endcase
355+
end
356+
234357
// ------------
235358
// Flush CTRL
236359
// ------------

0 commit comments

Comments
 (0)