mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 05:37:16 -04:00
Implement WFI as stalling, fix issue #51
This commit is contained in:
parent
f1272d0c55
commit
5aa9084279
5 changed files with 57 additions and 8 deletions
|
@ -228,6 +228,9 @@ module ariane
|
|||
logic flush_ctrl_ex;
|
||||
logic flush_tlb_ctrl_ex;
|
||||
logic sfence_vma_commit_controller;
|
||||
logic halt_ctrl_commit;
|
||||
logic halt_debug_ctrl;
|
||||
logic halt_csr_ctrl;
|
||||
|
||||
assign sec_lvl_o = priv_lvl;
|
||||
// --------------
|
||||
|
@ -426,6 +429,7 @@ module ariane
|
|||
// Commit
|
||||
// ---------
|
||||
commit_stage commit_stage_i (
|
||||
.halt_i ( halt_ctrl_commit ),
|
||||
.exception_o ( ex_commit ),
|
||||
.commit_instr_i ( commit_instr_id_commit ),
|
||||
.commit_ack_o ( commit_ack ),
|
||||
|
@ -452,6 +456,7 @@ module ariane
|
|||
)
|
||||
csr_regfile_i (
|
||||
.flush_o ( flush_csr_ctrl ),
|
||||
.halt_csr_o ( halt_csr_ctrl ),
|
||||
.commit_ack_i ( commit_ack ),
|
||||
.ex_i ( ex_commit ),
|
||||
.csr_op_i ( csr_op_commit_csr ),
|
||||
|
@ -489,6 +494,10 @@ module ariane
|
|||
.flush_id_o ( flush_ctrl_id ),
|
||||
.flush_ex_o ( flush_ctrl_ex ),
|
||||
.flush_tlb_o ( flush_tlb_ctrl_ex ),
|
||||
|
||||
.halt_csr_i ( halt_csr_ctrl ),
|
||||
.halt_debug_i ( 1'b0 ),
|
||||
.halt_o ( halt_ctrl_commit ),
|
||||
// control ports
|
||||
.eret_i ( eret ),
|
||||
.ex_i ( ex_commit ),
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
import ariane_pkg::*;
|
||||
|
||||
module commit_stage (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
|
||||
input logic halt_i, // request to halt the core
|
||||
|
||||
output exception exception_o, // take exception to controller
|
||||
|
||||
|
@ -66,7 +68,8 @@ module commit_stage (
|
|||
sfence_vma_o = 1'b0;
|
||||
|
||||
// we will not commit the instruction if we took an exception
|
||||
if (commit_instr_i.valid) begin
|
||||
// but we do not commit the instruction if we requested a halt
|
||||
if (commit_instr_i.valid && !halt_i) begin
|
||||
// register will be the all zero register.
|
||||
// and also acknowledge the instruction, this is mainly done for the instruction tracer
|
||||
// as it will listen on the instruction ack signal. For the overall result it does not make any
|
||||
|
|
|
@ -31,6 +31,9 @@ module controller (
|
|||
output logic flush_ex_o, // Flush EX stage
|
||||
output logic flush_tlb_o, // Flush TLBs
|
||||
|
||||
input logic halt_csr_i, // Halt request from CSR (WFI instruction)
|
||||
input logic halt_debug_i, // Halt request from debug
|
||||
output logic halt_o, // Halt signal to commit stage
|
||||
input logic eret_i, // Return from exception
|
||||
input exception ex_i, // We got an exception, flush the pipeline
|
||||
input branchpredict resolved_branch_i, // We got a resolved branch, check if we need to flush the front-end
|
||||
|
@ -111,5 +114,11 @@ module controller (
|
|||
end
|
||||
|
||||
end
|
||||
// flush on exception
|
||||
|
||||
// ----------------------
|
||||
// Halt Logic
|
||||
// ----------------------
|
||||
always_comb begin
|
||||
halt_o = halt_debug_i || halt_csr_i;
|
||||
end
|
||||
endmodule
|
||||
|
|
|
@ -27,6 +27,7 @@ module csr_regfile #(
|
|||
input logic rst_ni, // Asynchronous reset active low
|
||||
// send a flush request out if a CSR with a side effect has changed (e.g. written)
|
||||
output logic flush_o,
|
||||
output logic halt_csr_o, // halt requested
|
||||
// commit acknowledge
|
||||
input logic commit_ack_i, // Commit acknowledged a instruction -> increase instret CSR
|
||||
// Core and Cluster ID
|
||||
|
@ -131,9 +132,11 @@ module csr_regfile #(
|
|||
logic [63:0] scause_q, scause_n;
|
||||
logic [63:0] stval_q, stval_n;
|
||||
|
||||
logic [63:0] cycle_q, cycle_n;
|
||||
logic [63:0] time_q, time_n;
|
||||
logic [63:0] instret_q, instret_n;
|
||||
logic wfi_n, wfi_q;
|
||||
|
||||
logic [63:0] cycle_q, cycle_n;
|
||||
logic [63:0] time_q, time_n;
|
||||
logic [63:0] instret_q, instret_n;
|
||||
|
||||
typedef struct packed {
|
||||
logic [3:0] mode;
|
||||
|
@ -466,6 +469,8 @@ module csr_regfile #(
|
|||
// --------------------------------------
|
||||
always_comb begin : exception_ctrl
|
||||
automatic logic [63:0] interrupt_cause = '0;
|
||||
// wait for interrupt register
|
||||
wfi_n = wfi_q;
|
||||
|
||||
csr_exception_o = {
|
||||
64'b0, 64'b0, 1'b0
|
||||
|
@ -532,6 +537,17 @@ module csr_regfile #(
|
|||
// this spares the extra wiring from commit to CSR and back to commit
|
||||
csr_exception_o.valid = 1'b1;
|
||||
end
|
||||
|
||||
// -------------------
|
||||
// Wait for Interrupt
|
||||
// -------------------
|
||||
// if there is any interrupt pending un-stall the core
|
||||
if (|mip_q) begin
|
||||
wfi_n = 1'b0;
|
||||
// or alternatively if there is no exception pending, wait here for the interrupt
|
||||
end else if (csr_op_i == WFI && !ex_i.valid) begin
|
||||
wfi_n = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// -------------------
|
||||
|
@ -549,6 +565,7 @@ module csr_regfile #(
|
|||
assign tvm_o = mstatus_q.tvm;
|
||||
assign tw_o = mstatus_q.tw;
|
||||
assign tsr_o = mstatus_q.tsr;
|
||||
assign halt_csr_o = wfi_q;
|
||||
|
||||
// output assignments dependent on privilege mode
|
||||
always_comb begin : priv_output
|
||||
|
@ -599,6 +616,8 @@ module csr_regfile #(
|
|||
instret_q <= 64'b0;
|
||||
// aux registers
|
||||
en_ld_st_translation_q <= 1'b0;
|
||||
// wait for interrupt
|
||||
wfi_q <= 1'b0;
|
||||
end else begin
|
||||
priv_lvl_q <= priv_lvl_n;
|
||||
// machine mode registers
|
||||
|
@ -624,6 +643,8 @@ module csr_regfile #(
|
|||
instret_q <= instret_n;
|
||||
// aux registers
|
||||
en_ld_st_translation_q <= en_ld_st_translation_n;
|
||||
// wait for interrupt
|
||||
wfi_q <= wfi_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -121,8 +121,15 @@ module decoder (
|
|||
instruction_o.op = WFI;
|
||||
// if timeout wait is set, trap on an illegal instruction in S Mode
|
||||
// (after 0 cycles timeout)
|
||||
if (priv_lvl_i == PRIV_LVL_S && tw_i)
|
||||
if (priv_lvl_i == PRIV_LVL_S && tw_i) begin
|
||||
illegal_instr = 1'b1;
|
||||
instruction_o.op = ADD;
|
||||
end
|
||||
// we don't support U mode interrupts so WFI is illegal in this context
|
||||
if (priv_lvl_i == PRIV_LVL_U) begin
|
||||
illegal_instr = 1'b1;
|
||||
instruction_o.op = ADD;
|
||||
end
|
||||
end
|
||||
// SFENCE.VMA
|
||||
default: begin
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue