Vaguely implement wfi
This commit is contained in:
parent
375a6d60b7
commit
cc6a6c09ba
|
@ -185,6 +185,7 @@ wire [W_ADDR-1:0] d_jump_offs;
|
||||||
wire d_jump_is_regoffs;
|
wire d_jump_is_regoffs;
|
||||||
wire [W_ADDR-1:0] d_pc;
|
wire [W_ADDR-1:0] d_pc;
|
||||||
wire [W_EXCEPT-1:0] d_except;
|
wire [W_EXCEPT-1:0] d_except;
|
||||||
|
wire d_wfi;
|
||||||
wire d_csr_ren;
|
wire d_csr_ren;
|
||||||
wire d_csr_wen;
|
wire d_csr_wen;
|
||||||
wire [1:0] d_csr_wtype;
|
wire [1:0] d_csr_wtype;
|
||||||
|
@ -229,7 +230,8 @@ hazard3_decode #(
|
||||||
.d_branchcond (d_branchcond),
|
.d_branchcond (d_branchcond),
|
||||||
.d_jump_offs (d_jump_offs),
|
.d_jump_offs (d_jump_offs),
|
||||||
.d_jump_is_regoffs (d_jump_is_regoffs),
|
.d_jump_is_regoffs (d_jump_is_regoffs),
|
||||||
.d_except (d_except)
|
.d_except (d_except),
|
||||||
|
.d_wfi (d_wfi)
|
||||||
);
|
);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -267,6 +269,7 @@ reg [W_DATA-1:0] xm_result;
|
||||||
reg [W_DATA-1:0] xm_store_data;
|
reg [W_DATA-1:0] xm_store_data;
|
||||||
reg [W_MEMOP-1:0] xm_memop;
|
reg [W_MEMOP-1:0] xm_memop;
|
||||||
reg [W_EXCEPT-1:0] xm_except;
|
reg [W_EXCEPT-1:0] xm_except;
|
||||||
|
reg xm_wfi;
|
||||||
reg xm_delay_irq_entry;
|
reg xm_delay_irq_entry;
|
||||||
|
|
||||||
|
|
||||||
|
@ -496,6 +499,7 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
end
|
end
|
||||||
|
|
||||||
wire [W_ADDR-1:0] m_exception_return_addr;
|
wire [W_ADDR-1:0] m_exception_return_addr;
|
||||||
|
wire m_wfi_stall_clear;
|
||||||
|
|
||||||
// If an instruction causes an exceptional condition we do not consider it to have retired.
|
// If an instruction causes an exceptional condition we do not consider it to have retired.
|
||||||
wire x_except_counts_as_retire = x_except == EXCEPT_EBREAK || x_except == EXCEPT_MRET || x_except == EXCEPT_ECALL;
|
wire x_except_counts_as_retire = x_except == EXCEPT_EBREAK || x_except == EXCEPT_MRET || x_except == EXCEPT_ECALL;
|
||||||
|
@ -542,6 +546,7 @@ hazard3_csr #(
|
||||||
.trap_enter_rdy (m_trap_enter_rdy),
|
.trap_enter_rdy (m_trap_enter_rdy),
|
||||||
.loadstore_dphase_pending (!xm_memop[3]),
|
.loadstore_dphase_pending (!xm_memop[3]),
|
||||||
.mepc_in (m_exception_return_addr),
|
.mepc_in (m_exception_return_addr),
|
||||||
|
.wfi_stall_clear (m_wfi_stall_clear),
|
||||||
|
|
||||||
// IRQ and exception requests
|
// IRQ and exception requests
|
||||||
.delay_irq_entry (xm_delay_irq_entry),
|
.delay_irq_entry (xm_delay_irq_entry),
|
||||||
|
@ -565,6 +570,7 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
xm_memop <= MEMOP_NONE;
|
xm_memop <= MEMOP_NONE;
|
||||||
xm_except <= EXCEPT_NONE;
|
xm_except <= EXCEPT_NONE;
|
||||||
|
xm_wfi <= 1'b0;
|
||||||
{xm_rs1, xm_rs2, xm_rd} <= {3 * W_REGADDR{1'b0}};
|
{xm_rs1, xm_rs2, xm_rd} <= {3 * W_REGADDR{1'b0}};
|
||||||
end else begin
|
end else begin
|
||||||
if (!m_stall) begin
|
if (!m_stall) begin
|
||||||
|
@ -572,11 +578,13 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
// If the transfer is unaligned, make sure it is completely NOP'd on the bus
|
// If the transfer is unaligned, make sure it is completely NOP'd on the bus
|
||||||
xm_memop <= d_memop | {x_unaligned_addr, 3'h0};
|
xm_memop <= d_memop | {x_unaligned_addr, 3'h0};
|
||||||
xm_except <= x_except;
|
xm_except <= x_except;
|
||||||
|
xm_wfi <= d_wfi;
|
||||||
if (x_stall || m_trap_enter_soon) begin
|
if (x_stall || m_trap_enter_soon) begin
|
||||||
// Insert bubble
|
// Insert bubble
|
||||||
xm_rd <= {W_REGADDR{1'b0}};
|
xm_rd <= {W_REGADDR{1'b0}};
|
||||||
xm_memop <= MEMOP_NONE;
|
xm_memop <= MEMOP_NONE;
|
||||||
xm_except <= EXCEPT_NONE;
|
xm_except <= EXCEPT_NONE;
|
||||||
|
xm_wfi <= 1'b0;
|
||||||
end
|
end
|
||||||
end else if (bus_dph_err_d) begin
|
end else if (bus_dph_err_d) begin
|
||||||
// First phase of 2-phase AHBL error response. Pass the exception along on
|
// First phase of 2-phase AHBL error response. Pass the exception along on
|
||||||
|
@ -586,6 +594,7 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
assert(!xm_memop[3]); // Not NONE
|
assert(!xm_memop[3]); // Not NONE
|
||||||
`endif
|
`endif
|
||||||
xm_except <= xm_memop <= MEMOP_LBU ? EXCEPT_LOAD_FAULT : EXCEPT_STORE_FAULT;
|
xm_except <= xm_memop <= MEMOP_LBU ? EXCEPT_LOAD_FAULT : EXCEPT_STORE_FAULT;
|
||||||
|
xm_wfi <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -624,7 +633,9 @@ assign f_jump_target = m_trap_enter_vld ? m_trap_addr : x_jump_target;
|
||||||
assign x_jump_not_except = !m_trap_enter_vld;
|
assign x_jump_not_except = !m_trap_enter_vld;
|
||||||
|
|
||||||
wire m_bus_stall = !xm_memop[3] && !bus_dph_ready_d;
|
wire m_bus_stall = !xm_memop[3] && !bus_dph_ready_d;
|
||||||
assign m_stall = m_bus_stall || (m_trap_enter_vld && !m_trap_enter_rdy && !m_trap_is_irq);
|
assign m_stall = m_bus_stall ||
|
||||||
|
(m_trap_enter_vld && !m_trap_enter_rdy && !m_trap_is_irq) ||
|
||||||
|
(xm_wfi && !m_wfi_stall_clear);
|
||||||
|
|
||||||
// Exception is taken against the instruction currently in M, so walk the PC
|
// Exception is taken against the instruction currently in M, so walk the PC
|
||||||
// back. IRQ is taken "in between" the instruction in M and the instruction
|
// back. IRQ is taken "in between" the instruction in M and the instruction
|
||||||
|
|
|
@ -91,6 +91,7 @@ module hazard3_csr #(
|
||||||
// mode.
|
// mode.
|
||||||
input wire loadstore_dphase_pending,
|
input wire loadstore_dphase_pending,
|
||||||
input wire [XLEN-1:0] mepc_in,
|
input wire [XLEN-1:0] mepc_in,
|
||||||
|
output wire wfi_stall_clear,
|
||||||
|
|
||||||
// Exceptions must *not* be a function of bus stall.
|
// Exceptions must *not* be a function of bus stall.
|
||||||
input wire [W_EXCEPT-1:0] except,
|
input wire [W_EXCEPT-1:0] except,
|
||||||
|
@ -1019,6 +1020,10 @@ wire [31:0] mip_no_global = mip & ~(32'h800 & ~{XLEN{midcr_eivect}});
|
||||||
wire standard_irq_active = |(mip_no_global & mie) && mstatus_mie && !dcsr_step;
|
wire standard_irq_active = |(mip_no_global & mie) && mstatus_mie && !dcsr_step;
|
||||||
wire external_irq_active = external_irq_pending && mstatus_mie && !dcsr_step && mie_meie;
|
wire external_irq_active = external_irq_pending && mstatus_mie && !dcsr_step && mie_meie;
|
||||||
|
|
||||||
|
// WFI clear respects individual interrupt enables but ignores mstatus.mie.
|
||||||
|
// Additionally, wfi is treated as a nop during single-stepping and D-mode.
|
||||||
|
assign wfi_stall_clear = |(mip & mie) || dcsr_step || debug_mode || want_halt_irq_if_no_exception;
|
||||||
|
|
||||||
wire [4:0] external_irq_num;
|
wire [4:0] external_irq_num;
|
||||||
wire [3:0] standard_irq_num;
|
wire [3:0] standard_irq_num;
|
||||||
assign mlei = external_irq_num;
|
assign mlei = external_irq_num;
|
||||||
|
|
|
@ -56,7 +56,8 @@ module hazard3_decode #(
|
||||||
output reg [W_BCOND-1:0] d_branchcond,
|
output reg [W_BCOND-1:0] d_branchcond,
|
||||||
output reg [W_ADDR-1:0] d_jump_offs,
|
output reg [W_ADDR-1:0] d_jump_offs,
|
||||||
output reg d_jump_is_regoffs,
|
output reg d_jump_is_regoffs,
|
||||||
output reg [W_EXCEPT-1:0] d_except
|
output reg [W_EXCEPT-1:0] d_except,
|
||||||
|
output reg d_wfi
|
||||||
);
|
);
|
||||||
|
|
||||||
`include "rv_opcodes.vh"
|
`include "rv_opcodes.vh"
|
||||||
|
@ -193,6 +194,7 @@ always @ (*) begin
|
||||||
d_jump_is_regoffs = 1'b0;
|
d_jump_is_regoffs = 1'b0;
|
||||||
d_invalid_32bit = 1'b0;
|
d_invalid_32bit = 1'b0;
|
||||||
d_except = EXCEPT_NONE;
|
d_except = EXCEPT_NONE;
|
||||||
|
d_wfi = 1'b0;
|
||||||
|
|
||||||
casez (d_instr)
|
casez (d_instr)
|
||||||
RV_BEQ: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_SUB; d_branchcond = BCOND_ZERO; end
|
RV_BEQ: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_SUB; d_branchcond = BCOND_ZERO; end
|
||||||
|
@ -251,6 +253,7 @@ always @ (*) begin
|
||||||
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) 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
|
||||||
default: begin d_invalid_32bit = 1'b1; end
|
default: begin d_invalid_32bit = 1'b1; end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
@ -263,6 +266,7 @@ always @ (*) begin
|
||||||
d_csr_ren = 1'b0;
|
d_csr_ren = 1'b0;
|
||||||
d_csr_wen = 1'b0;
|
d_csr_wen = 1'b0;
|
||||||
d_except = EXCEPT_NONE;
|
d_except = EXCEPT_NONE;
|
||||||
|
d_wfi = 1'b0;
|
||||||
if (EXTENSION_M)
|
if (EXTENSION_M)
|
||||||
d_aluop = ALUOP_ADD;
|
d_aluop = ALUOP_ADD;
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ localparam RV_CSRRSI = 32'b?????????????????110?????1110011;
|
||||||
localparam RV_CSRRCI = 32'b?????????????????111?????1110011;
|
localparam RV_CSRRCI = 32'b?????????????????111?????1110011;
|
||||||
localparam RV_MRET = 32'b00110000001000000000000001110011;
|
localparam RV_MRET = 32'b00110000001000000000000001110011;
|
||||||
localparam RV_SYSTEM = 32'b?????????????????????????1110011;
|
localparam RV_SYSTEM = 32'b?????????????????????????1110011;
|
||||||
|
localparam RV_WFI = 32'b00010000010100000000000001110011;
|
||||||
|
|
||||||
// M extension
|
// M extension
|
||||||
localparam RV_MUL = 32'b0000001??????????000?????0110011;
|
localparam RV_MUL = 32'b0000001??????????000?????0110011;
|
||||||
|
@ -144,4 +145,4 @@ localparam RV_NOZ_CSRRC = 32'b00000000000000000011000001110011;
|
||||||
localparam RV_NOZ_CSRRWI = 32'b00000000000000000101000001110011;
|
localparam RV_NOZ_CSRRWI = 32'b00000000000000000101000001110011;
|
||||||
localparam RV_NOZ_CSRRSI = 32'b00000000000000000110000001110011;
|
localparam RV_NOZ_CSRRSI = 32'b00000000000000000110000001110011;
|
||||||
localparam RV_NOZ_CSRRCI = 32'b00000000000000000111000001110011;
|
localparam RV_NOZ_CSRRCI = 32'b00000000000000000111000001110011;
|
||||||
localparam RV_NOZ_SYSTEM = 32'b00000000000000000000000001110011;
|
localparam RV_NOZ_SYSTEM = 32'b00000000000000000000000001110011;
|
||||||
|
|
Loading…
Reference in New Issue