Add mstatus.tw to control U-mode WFI, and prevent mret execution in U-mode.
This commit is contained in:
parent
10ca3aec80
commit
51750eb81d
|
@ -187,11 +187,13 @@ wire d_csr_wen;
|
||||||
wire [1:0] d_csr_wtype;
|
wire [1:0] d_csr_wtype;
|
||||||
wire d_csr_w_imm;
|
wire d_csr_w_imm;
|
||||||
|
|
||||||
wire x_jump_not_except;
|
wire x_jump_not_except;
|
||||||
|
wire x_mmode_execution;
|
||||||
|
wire x_permit_wfi;
|
||||||
|
|
||||||
hazard3_decode #(
|
hazard3_decode #(
|
||||||
`include "hazard3_config_inst.vh"
|
`include "hazard3_config_inst.vh"
|
||||||
) inst_hazard3_decode (
|
) decode_u (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst_n (rst_n),
|
.rst_n (rst_n),
|
||||||
|
|
||||||
|
@ -204,6 +206,8 @@ hazard3_decode #(
|
||||||
.x_jump_not_except (x_jump_not_except),
|
.x_jump_not_except (x_jump_not_except),
|
||||||
|
|
||||||
.debug_mode (debug_mode),
|
.debug_mode (debug_mode),
|
||||||
|
.m_mode (x_mmode_execution),
|
||||||
|
.permit_wfi (x_permit_wfi),
|
||||||
|
|
||||||
.d_starved (d_starved),
|
.d_starved (d_starved),
|
||||||
.x_stall (x_stall),
|
.x_stall (x_stall),
|
||||||
|
@ -257,8 +261,6 @@ wire m_trap_enter_vld;
|
||||||
wire m_trap_enter_soon;
|
wire m_trap_enter_soon;
|
||||||
wire m_trap_enter_rdy = f_jump_rdy;
|
wire m_trap_enter_rdy = f_jump_rdy;
|
||||||
|
|
||||||
// Privilege state outputs from CSR block
|
|
||||||
wire x_mmode_execution;
|
|
||||||
wire x_mmode_loadstore;
|
wire x_mmode_loadstore;
|
||||||
wire m_mmode_trap_entry;
|
wire m_mmode_trap_entry;
|
||||||
|
|
||||||
|
@ -821,7 +823,7 @@ wire m_dphase_in_flight = xm_memop != MEMOP_NONE && xm_memop != MEMOP_AMO;
|
||||||
hazard3_csr #(
|
hazard3_csr #(
|
||||||
.XLEN (W_DATA),
|
.XLEN (W_DATA),
|
||||||
`include "hazard3_config_inst.vh"
|
`include "hazard3_config_inst.vh"
|
||||||
) inst_hazard3_csr (
|
) csr_u (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst_n (rst_n),
|
.rst_n (rst_n),
|
||||||
|
|
||||||
|
@ -878,6 +880,7 @@ hazard3_csr #(
|
||||||
.pmp_cfg_rdata (x_pmp_cfg_rdata),
|
.pmp_cfg_rdata (x_pmp_cfg_rdata),
|
||||||
|
|
||||||
// Other CSR-specific signalling
|
// Other CSR-specific signalling
|
||||||
|
.permit_wfi (x_permit_wfi),
|
||||||
.instr_ret (|x_instr_ret)
|
.instr_ret (|x_instr_ret)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ module hazard3_csr #(
|
||||||
input wire [W_DATA-1:0] pmp_cfg_rdata,
|
input wire [W_DATA-1:0] pmp_cfg_rdata,
|
||||||
|
|
||||||
// Other CSR-specific signalling
|
// Other CSR-specific signalling
|
||||||
|
output wire permit_wfi,
|
||||||
input wire instr_ret
|
input wire instr_ret
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -146,13 +147,14 @@ end
|
||||||
|
|
||||||
wire debug_suppresses_trap_update = DEBUG_SUPPORT && (debug_mode || enter_debug_mode);
|
wire debug_suppresses_trap_update = DEBUG_SUPPORT && (debug_mode || enter_debug_mode);
|
||||||
|
|
||||||
|
// Core execution state, 1 -> M-mode, 0 -> U-mode (if implemented)
|
||||||
// Two-level interrupt enable stack, shuffled on entry/exit:
|
|
||||||
reg m_mode;
|
reg m_mode;
|
||||||
|
|
||||||
reg mstatus_mpie;
|
reg mstatus_mpie;
|
||||||
reg mstatus_mie;
|
reg mstatus_mie;
|
||||||
reg mstatus_mpp; // only MSB is implemented
|
reg mstatus_mpp; // only MSB is implemented
|
||||||
reg mstatus_mprv;
|
reg mstatus_mprv;
|
||||||
|
reg mstatus_tw;
|
||||||
|
|
||||||
wire wen_m_mode = wen && (m_mode || debug_mode);
|
wire wen_m_mode = wen && (m_mode || debug_mode);
|
||||||
|
|
||||||
|
@ -163,6 +165,7 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
mstatus_mie <= 1'b0;
|
mstatus_mie <= 1'b0;
|
||||||
mstatus_mpp <= 1'b1;
|
mstatus_mpp <= 1'b1;
|
||||||
mstatus_mprv <= 1'b0;
|
mstatus_mprv <= 1'b0;
|
||||||
|
mstatus_tw <= 1'b0;
|
||||||
end else if (CSR_M_TRAP) begin
|
end else if (CSR_M_TRAP) begin
|
||||||
if (trap_enter_vld && trap_enter_rdy && !debug_suppresses_trap_update) begin
|
if (trap_enter_vld && trap_enter_rdy && !debug_suppresses_trap_update) begin
|
||||||
if (except == EXCEPT_MRET) begin
|
if (except == EXCEPT_MRET) begin
|
||||||
|
@ -184,7 +187,8 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
mstatus_mie <= wdata_update[3];
|
mstatus_mie <= wdata_update[3];
|
||||||
mstatus_mprv <= wdata_update[17];
|
mstatus_mprv <= wdata_update[17];
|
||||||
// Note only the MSB of MPP is implemented. It reads back as 11 or 00.
|
// Note only the MSB of MPP is implemented. It reads back as 11 or 00.
|
||||||
mstatus_mpp <= wdata_update[12];
|
mstatus_mpp <= wdata_update[12] || !U_MODE;
|
||||||
|
mstatus_tw <= wdata_update[21] && U_MODE;
|
||||||
end else if (wen && debug_mode && addr == DCSR && U_MODE && DEBUG_SUPPORT) begin
|
end else if (wen && debug_mode && addr == DCSR && U_MODE && DEBUG_SUPPORT) begin
|
||||||
// Debugger can change/observe core state directly through
|
// Debugger can change/observe core state directly through
|
||||||
// dcsr.prv (this doesn't affect debugger operation, as all
|
// dcsr.prv (this doesn't affect debugger operation, as all
|
||||||
|
@ -195,6 +199,9 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// Simply trap all U-mode WFIs if timeout bit is set
|
||||||
|
assign permit_wfi = m_mode || !mstatus_tw;
|
||||||
|
|
||||||
reg [XLEN-1:0] mscratch;
|
reg [XLEN-1:0] mscratch;
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
|
@ -510,10 +517,10 @@ always @ (*) begin
|
||||||
1'b0, // Never any dirty state besides GPRs
|
1'b0, // Never any dirty state besides GPRs
|
||||||
8'd0, // (WPRI)
|
8'd0, // (WPRI)
|
||||||
1'b0, // TSR (Trap SRET), tied 0 if no S mode.
|
1'b0, // TSR (Trap SRET), tied 0 if no S mode.
|
||||||
1'b0, // TW (Timeout Wait), tied 0 if only M mode.
|
mstatus_tw, // TW (Timeout Wait)
|
||||||
1'b0, // TVM (trap virtual memory), tied 0 if no S mode.
|
1'b0, // TVM (trap virtual memory), tied 0 if no S mode.
|
||||||
1'b0, // MXR (Make eXecutable Readable), tied 0 if not S mode.
|
1'b0, // MXR (Make eXecutable Readable), tied 0 if no S mode.
|
||||||
1'b0, // SUM, tied 0, we have no S or U mode
|
1'b0, // SUM, tied 0 if no S mode
|
||||||
mstatus_mprv, // MPRV (modify privilege)
|
mstatus_mprv, // MPRV (modify privilege)
|
||||||
4'd0, // XS, FS always "off" (no extension state to clear!)
|
4'd0, // XS, FS always "off" (no extension state to clear!)
|
||||||
{2{mstatus_mpp}}, // MPP (M-mode previous privilege), only M and U supported
|
{2{mstatus_mpp}}, // MPP (M-mode previous privilege), only M and U supported
|
||||||
|
|
|
@ -10,23 +10,25 @@ module hazard3_decode #(
|
||||||
,
|
,
|
||||||
`include "hazard3_width_const.vh"
|
`include "hazard3_width_const.vh"
|
||||||
) (
|
) (
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst_n,
|
input wire rst_n,
|
||||||
|
|
||||||
input wire [31:0] fd_cir,
|
input wire [31:0] fd_cir,
|
||||||
input wire [1:0] fd_cir_err,
|
input wire [1:0] fd_cir_err,
|
||||||
input wire [1:0] fd_cir_vld,
|
input wire [1:0] fd_cir_vld,
|
||||||
output wire [1:0] df_cir_use,
|
output wire [1:0] df_cir_use,
|
||||||
output wire df_cir_lock,
|
output wire df_cir_lock,
|
||||||
output wire [W_ADDR-1:0] d_pc,
|
output wire [W_ADDR-1:0] d_pc,
|
||||||
|
|
||||||
input wire debug_mode,
|
input wire debug_mode,
|
||||||
|
input wire m_mode,
|
||||||
|
input wire permit_wfi,
|
||||||
|
|
||||||
output wire d_starved,
|
output wire d_starved,
|
||||||
input wire x_stall,
|
input wire x_stall,
|
||||||
input wire f_jump_now,
|
input wire f_jump_now,
|
||||||
input wire [W_ADDR-1:0] f_jump_target,
|
input wire [W_ADDR-1:0] f_jump_target,
|
||||||
input wire x_jump_not_except,
|
input wire x_jump_not_except,
|
||||||
|
|
||||||
output reg [W_DATA-1:0] d_imm,
|
output reg [W_DATA-1:0] d_imm,
|
||||||
output reg [W_REGADDR-1:0] d_rs1,
|
output reg [W_REGADDR-1:0] d_rs1,
|
||||||
|
@ -290,17 +292,18 @@ always @ (*) begin
|
||||||
RV_ZIP: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_ZIP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
RV_ZIP: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_ZIP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
|
||||||
RV_FENCE: begin d_rs2 = X0; end // NOP, note rs1/rd are zero in instruction
|
RV_FENCE: begin d_rs2 = X0; end // NOP, note rs1/rd are zero in instruction
|
||||||
RV_FENCE_I: if (EXTENSION_ZIFENCEI) begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; end else begin d_invalid_32bit = 1'b1; end // note rs1/rs2/rd are zero in instruction
|
RV_FENCE_I: if (EXTENSION_ZIFENCEI) begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; end else begin d_invalid_32bit = 1'b1; end // note rs1/rs2/rd are zero in instruction
|
||||||
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_CSRRS: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRS: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_CSRRC: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRC: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_CSRRWI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRWI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_CSRRSI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRSI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_CSRRCI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
RV_CSRRCI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_ECALL: if (HAVE_CSR) begin d_except = EXCEPT_ECALL; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
RV_ECALL: if (HAVE_CSR) begin d_except = EXCEPT_ECALL; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_EBREAK: if (HAVE_CSR) begin d_except = EXCEPT_EBREAK; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
RV_EBREAK: if (HAVE_CSR) begin d_except = EXCEPT_EBREAK; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_MRET: if (HAVE_CSR) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
RV_MRET: if (HAVE_CSR && m_mode) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
RV_WFI: if (HAVE_CSR) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
RV_WFI: if (HAVE_CSR && permit_wfi) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
||||||
|
|
||||||
default: begin d_invalid_32bit = 1'b1; end
|
default: begin d_invalid_32bit = 1'b1; end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue