@@ -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