Plumb privilege state through to the bus ports
This commit is contained in:
parent
cfed35b3da
commit
4878a752d6
|
@ -81,14 +81,12 @@ wire debug_mode;
|
||||||
assign dbg_halted = DEBUG_SUPPORT && debug_mode;
|
assign dbg_halted = DEBUG_SUPPORT && debug_mode;
|
||||||
assign dbg_running = DEBUG_SUPPORT && !debug_mode;
|
assign dbg_running = DEBUG_SUPPORT && !debug_mode;
|
||||||
|
|
||||||
assign bus_priv_i = 1'b1;
|
|
||||||
always @ (*) bus_priv_d = 1'b1;
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Pipe Stage F
|
// Pipe Stage F
|
||||||
|
|
||||||
wire f_jump_req;
|
wire f_jump_req;
|
||||||
wire [W_ADDR-1:0] f_jump_target;
|
wire [W_ADDR-1:0] f_jump_target;
|
||||||
|
wire f_jump_priv;
|
||||||
wire f_jump_rdy;
|
wire f_jump_rdy;
|
||||||
wire f_jump_now = f_jump_req && f_jump_rdy;
|
wire f_jump_now = f_jump_req && f_jump_rdy;
|
||||||
|
|
||||||
|
@ -118,6 +116,7 @@ hazard3_frontend #(
|
||||||
|
|
||||||
.mem_size (f_mem_size),
|
.mem_size (f_mem_size),
|
||||||
.mem_addr (bus_haddr_i),
|
.mem_addr (bus_haddr_i),
|
||||||
|
.mem_priv (bus_priv_i),
|
||||||
.mem_addr_vld (bus_aph_req_i),
|
.mem_addr_vld (bus_aph_req_i),
|
||||||
.mem_addr_rdy (bus_aph_ready_i),
|
.mem_addr_rdy (bus_aph_ready_i),
|
||||||
|
|
||||||
|
@ -126,6 +125,7 @@ hazard3_frontend #(
|
||||||
.mem_data_vld (bus_dph_ready_i),
|
.mem_data_vld (bus_dph_ready_i),
|
||||||
|
|
||||||
.jump_target (f_jump_target),
|
.jump_target (f_jump_target),
|
||||||
|
.jump_priv (f_jump_priv),
|
||||||
.jump_target_vld (f_jump_req),
|
.jump_target_vld (f_jump_req),
|
||||||
.jump_target_rdy (f_jump_rdy),
|
.jump_target_rdy (f_jump_rdy),
|
||||||
|
|
||||||
|
@ -257,6 +257,11 @@ 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 m_mmode_trap_entry;
|
||||||
|
|
||||||
reg [W_REGADDR-1:0] xm_rs1;
|
reg [W_REGADDR-1:0] xm_rs1;
|
||||||
reg [W_REGADDR-1:0] xm_rs2;
|
reg [W_REGADDR-1:0] xm_rs2;
|
||||||
reg [W_REGADDR-1:0] xm_rd;
|
reg [W_REGADDR-1:0] xm_rd;
|
||||||
|
@ -554,6 +559,7 @@ always @ (*) begin
|
||||||
// Need to be careful not to use anything hready-sourced to gate htrans!
|
// Need to be careful not to use anything hready-sourced to gate htrans!
|
||||||
bus_haddr_d = x_addr_sum;
|
bus_haddr_d = x_addr_sum;
|
||||||
bus_hwrite_d = x_memop_write;
|
bus_hwrite_d = x_memop_write;
|
||||||
|
bus_priv_d = x_mmode_loadstore;
|
||||||
case (d_memop)
|
case (d_memop)
|
||||||
MEMOP_LW: bus_hsize_d = HSIZE_WORD;
|
MEMOP_LW: bus_hsize_d = HSIZE_WORD;
|
||||||
MEMOP_SW: bus_hsize_d = HSIZE_WORD;
|
MEMOP_SW: bus_hsize_d = HSIZE_WORD;
|
||||||
|
@ -804,6 +810,10 @@ hazard3_csr #(
|
||||||
.mepc_in (m_exception_return_addr),
|
.mepc_in (m_exception_return_addr),
|
||||||
.wfi_stall_clear (m_wfi_stall_clear),
|
.wfi_stall_clear (m_wfi_stall_clear),
|
||||||
|
|
||||||
|
.m_mode_execution (x_mmode_execution),
|
||||||
|
.m_mode_loadstore (x_mmode_loadstore),
|
||||||
|
.m_mode_trap_entry (m_mmode_trap_entry),
|
||||||
|
|
||||||
// IRQ and exception requests
|
// IRQ and exception requests
|
||||||
.delay_irq_entry (xm_delay_irq_entry),
|
.delay_irq_entry (xm_delay_irq_entry),
|
||||||
.irq (irq),
|
.irq (irq),
|
||||||
|
@ -887,6 +897,7 @@ reg [W_DATA-1:0] m_result;
|
||||||
|
|
||||||
assign f_jump_req = x_jump_req || m_trap_enter_vld;
|
assign f_jump_req = x_jump_req || m_trap_enter_vld;
|
||||||
assign f_jump_target = m_trap_enter_vld ? m_trap_addr : x_jump_target;
|
assign f_jump_target = m_trap_enter_vld ? m_trap_addr : x_jump_target;
|
||||||
|
assign f_jump_priv = m_trap_enter_vld ? m_mmode_trap_entry : x_mmode_execution;
|
||||||
assign x_jump_not_except = !m_trap_enter_vld;
|
assign x_jump_not_except = !m_trap_enter_vld;
|
||||||
|
|
||||||
// EXCEPT_NONE clause is needed in the following sequence:
|
// EXCEPT_NONE clause is needed in the following sequence:
|
||||||
|
|
|
@ -81,6 +81,11 @@ module hazard3_csr #(
|
||||||
input wire [XLEN-1:0] mepc_in,
|
input wire [XLEN-1:0] mepc_in,
|
||||||
output wire wfi_stall_clear,
|
output wire wfi_stall_clear,
|
||||||
|
|
||||||
|
// Each of these may be performed at a different privilege level from the others:
|
||||||
|
output wire m_mode_execution,
|
||||||
|
output wire m_mode_trap_entry,
|
||||||
|
output wire m_mode_loadstore,
|
||||||
|
|
||||||
// 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,
|
||||||
|
|
||||||
|
@ -90,6 +95,7 @@ module hazard3_csr #(
|
||||||
input wire irq_software,
|
input wire irq_software,
|
||||||
input wire irq_timer,
|
input wire irq_timer,
|
||||||
|
|
||||||
|
|
||||||
// Other CSR-specific signalling
|
// Other CSR-specific signalling
|
||||||
input wire instr_ret
|
input wire instr_ret
|
||||||
);
|
);
|
||||||
|
@ -1027,6 +1033,32 @@ assign trap_enter_soon = trap_enter_vld || (
|
||||||
assign mcause_irq_next = !exception_req_any;
|
assign mcause_irq_next = !exception_req_any;
|
||||||
assign mcause_code_next = exception_req_any ? {2'h0, except} : mcause_irq_num;
|
assign mcause_code_next = exception_req_any ? {2'h0, except} : mcause_irq_num;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Privilege state outputs
|
||||||
|
|
||||||
|
// Effective privilege for execution. Used for:
|
||||||
|
// - Privilege level of branch target fetches (frontend keeps fetch privilege
|
||||||
|
// constant during sequential fetch)
|
||||||
|
// - Checking PC against PMP execute permission
|
||||||
|
|
||||||
|
assign m_mode_execution = !U_MODE || debug_mode || m_mode;
|
||||||
|
|
||||||
|
// Effective privilege for trap entry. Used for:
|
||||||
|
// - Privilege level of trap target fetches (frontend keeps fetch privilege
|
||||||
|
// constant during sequential fetch)
|
||||||
|
|
||||||
|
assign m_mode_trap_entry = !U_MODE || (
|
||||||
|
except == EXCEPT_MRET ? mstatus_mpp : 1'b1
|
||||||
|
);
|
||||||
|
|
||||||
|
// Effective privilege for load/stores. Used for:
|
||||||
|
// - Privilege level of load/stores on the bus
|
||||||
|
// - Checking load/stores against PMP read/write permission
|
||||||
|
|
||||||
|
assign m_mode_loadstore = !U_MODE || debug_mode || ( // FIXME how does this interact with load/store racing against debug entry?
|
||||||
|
mstatus_mprv ? mstatus_mpp : m_mode
|
||||||
|
);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ module hazard3_frontend #(
|
||||||
// may not be used to compute combinational outputs.
|
// may not be used to compute combinational outputs.
|
||||||
output wire mem_size, // 1'b1 -> 32 bit access
|
output wire mem_size, // 1'b1 -> 32 bit access
|
||||||
output wire [W_ADDR-1:0] mem_addr,
|
output wire [W_ADDR-1:0] mem_addr,
|
||||||
|
output wire mem_priv,
|
||||||
output wire mem_addr_vld,
|
output wire mem_addr_vld,
|
||||||
input wire mem_addr_rdy,
|
input wire mem_addr_rdy,
|
||||||
input wire [W_DATA-1:0] mem_data,
|
input wire [W_DATA-1:0] mem_data,
|
||||||
|
@ -32,6 +33,7 @@ module hazard3_frontend #(
|
||||||
// unless rdy is high. Processor *may* alter request during this time.
|
// unless rdy is high. Processor *may* alter request during this time.
|
||||||
// Inputs must not be a function of hready.
|
// Inputs must not be a function of hready.
|
||||||
input wire [W_ADDR-1:0] jump_target,
|
input wire [W_ADDR-1:0] jump_target,
|
||||||
|
input wire jump_priv,
|
||||||
input wire jump_target_vld,
|
input wire jump_target_vld,
|
||||||
output wire jump_target_rdy,
|
output wire jump_target_rdy,
|
||||||
|
|
||||||
|
@ -179,14 +181,18 @@ end
|
||||||
|
|
||||||
// Fetch addr runs ahead of the PC, in word increments.
|
// Fetch addr runs ahead of the PC, in word increments.
|
||||||
reg [W_ADDR-1:0] fetch_addr;
|
reg [W_ADDR-1:0] fetch_addr;
|
||||||
|
reg fetch_priv;
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
fetch_addr <= RESET_VECTOR;
|
fetch_addr <= RESET_VECTOR;
|
||||||
|
// M-mode at reset:
|
||||||
|
fetch_priv <= 1'b1;
|
||||||
end else begin
|
end else begin
|
||||||
if (jump_now) begin
|
if (jump_now) begin
|
||||||
// Post-increment if jump request is going straight through
|
// Post-increment if jump request is going straight through
|
||||||
fetch_addr <= {jump_target[W_ADDR-1:2] + (mem_addr_rdy && !mem_addr_hold), 2'b00};
|
fetch_addr <= {jump_target[W_ADDR-1:2] + (mem_addr_rdy && !mem_addr_hold), 2'b00};
|
||||||
|
fetch_priv <= jump_priv || !U_MODE;
|
||||||
end else if (mem_addr_vld && mem_addr_rdy) begin
|
end else if (mem_addr_vld && mem_addr_rdy) begin
|
||||||
fetch_addr <= fetch_addr + 32'h4;
|
fetch_addr <= fetch_addr + 32'h4;
|
||||||
end
|
end
|
||||||
|
@ -247,7 +253,7 @@ always @ (posedge clk or negedge rst_n) begin
|
||||||
// Make sure these clear properly (have been subtle historic bugs here)
|
// Make sure these clear properly (have been subtle historic bugs here)
|
||||||
assert(!unaligned_jump_aph);
|
assert(!unaligned_jump_aph);
|
||||||
assert(!unaligned_jump_dph);
|
assert(!unaligned_jump_dph);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
`endif
|
`endif
|
||||||
|
@ -263,19 +269,25 @@ always @ (posedge clk or negedge rst_n)
|
||||||
reset_holdoff <= 1'b0;
|
reset_holdoff <= 1'b0;
|
||||||
|
|
||||||
reg [W_ADDR-1:0] mem_addr_r;
|
reg [W_ADDR-1:0] mem_addr_r;
|
||||||
reg mem_addr_vld_r;
|
reg mem_priv_r;
|
||||||
|
reg mem_addr_vld_r;
|
||||||
|
|
||||||
// Downstream accesses are always word-sized word-aligned.
|
// Downstream accesses are always word-sized word-aligned.
|
||||||
assign mem_addr = mem_addr_r;
|
assign mem_addr = mem_addr_r;
|
||||||
|
assign mem_priv = mem_addr_r;
|
||||||
assign mem_addr_vld = mem_addr_vld_r && !reset_holdoff;
|
assign mem_addr_vld = mem_addr_vld_r && !reset_holdoff;
|
||||||
assign mem_size = 1'b1;
|
assign mem_size = 1'b1;
|
||||||
|
|
||||||
always @ (*) begin
|
always @ (*) begin
|
||||||
mem_addr_r = {W_ADDR{1'b0}};
|
mem_addr_r = {W_ADDR{1'b0}};
|
||||||
|
mem_priv_r = fetch_priv;
|
||||||
mem_addr_vld_r = 1'b1;
|
mem_addr_vld_r = 1'b1;
|
||||||
case (1'b1)
|
case (1'b1)
|
||||||
mem_addr_hold : begin mem_addr_r = fetch_addr; end
|
mem_addr_hold : begin mem_addr_r = fetch_addr; end
|
||||||
jump_target_vld : begin mem_addr_r = {jump_target[W_ADDR-1:2], 2'b00}; end
|
jump_target_vld : begin
|
||||||
|
mem_addr_r = {jump_target[W_ADDR-1:2], 2'b00};
|
||||||
|
mem_priv_r = jump_priv || !U_MODE;
|
||||||
|
end
|
||||||
DEBUG_SUPPORT && debug_mode : begin mem_addr_vld_r = 1'b0; end
|
DEBUG_SUPPORT && debug_mode : begin mem_addr_vld_r = 1'b0; end
|
||||||
!fetch_stall : begin mem_addr_r = fetch_addr; end
|
!fetch_stall : begin mem_addr_r = fetch_addr; end
|
||||||
default : begin mem_addr_vld_r = 1'b0; end
|
default : begin mem_addr_vld_r = 1'b0; end
|
||||||
|
@ -443,4 +455,6 @@ end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
`ifndef YOSYS
|
||||||
`default_nettype wire
|
`default_nettype wire
|
||||||
|
`endif
|
||||||
|
|
Loading…
Reference in New Issue