mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-22 21:17:46 -04:00
added support to abort MMU requests
This commit is contained in:
parent
02d51444d4
commit
f501c938f4
7 changed files with 73 additions and 32 deletions
|
@ -482,6 +482,7 @@ generate if (ENABLE_S_MODE) begin
|
|||
assign asid = satp.asid;
|
||||
//******************
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//MMU interface
|
||||
assign immu.mxr = mstatus.mxr;
|
||||
assign dmmu.mxr = mstatus.mxr;
|
||||
|
@ -489,13 +490,14 @@ generate if (ENABLE_S_MODE) begin
|
|||
assign dmmu.sum = mstatus.sum;
|
||||
assign immu.privilege = privilege_level;
|
||||
assign dmmu.privilege = mstatus.mprv ? mstatus.mpp : privilege_level;
|
||||
assign immu.ppn = satp.ppn;
|
||||
assign dmmu.ppn = satp.ppn;
|
||||
//******************
|
||||
assign immu.satp_ppn = satp.ppn;
|
||||
assign dmmu.satp_ppn = satp.ppn;
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
assign sip_mask = '{default:0, seip:1, stip:1, ssip:1};
|
||||
|
||||
//stvec
|
||||
////////////////////////////////////////////////////
|
||||
//STVEC
|
||||
logic [31:0] stvec_mask = '1;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
|
@ -504,7 +506,8 @@ generate if (ENABLE_S_MODE) begin
|
|||
stvec <= (updated_csr & stvec_mask);
|
||||
end
|
||||
|
||||
//satp
|
||||
////////////////////////////////////////////////////
|
||||
//SATP
|
||||
logic[XLEN-1:0] satp_mask;
|
||||
assign satp_mask = '1;
|
||||
always_ff @(posedge clk) begin
|
||||
|
|
|
@ -85,6 +85,7 @@ module fetch(
|
|||
logic flush_or_rst;
|
||||
fifo_interface #(.DATA_WIDTH($bits(fetch_attributes_t))) fetch_attr_fifo();
|
||||
|
||||
logic update_pc;
|
||||
logic new_mem_request;
|
||||
|
||||
//Cache related
|
||||
|
@ -95,10 +96,11 @@ module fetch(
|
|||
//Implementation
|
||||
////////////////////////////////////////////////////
|
||||
//Fetch PC
|
||||
assign update_pc = new_mem_request | gc_fetch_flush;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst)
|
||||
pc <= RESET_VEC;
|
||||
else if (new_mem_request | gc_fetch_flush)
|
||||
else if (update_pc)
|
||||
pc <= {next_pc[31:2], 2'b0};
|
||||
end
|
||||
|
||||
|
@ -115,7 +117,7 @@ module fetch(
|
|||
next_pc = pc_plus_4;
|
||||
end
|
||||
|
||||
assign bp.new_mem_request = new_mem_request | gc_fetch_flush;
|
||||
assign bp.new_mem_request = update_pc;
|
||||
assign bp.next_pc = next_pc;
|
||||
assign bp.if_pc = pc;
|
||||
|
||||
|
@ -129,6 +131,7 @@ module fetch(
|
|||
assign tlb.virtual_address = pc;
|
||||
assign tlb.execute = 1;
|
||||
assign tlb.rnw = 0;
|
||||
assign tlb.new_request = update_pc;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (new_mem_request)
|
||||
|
|
|
@ -136,7 +136,7 @@ endinterface
|
|||
|
||||
interface mmu_interface;
|
||||
//From TLB
|
||||
logic new_request;
|
||||
logic request;
|
||||
logic execute;
|
||||
logic rnw;
|
||||
logic [31:0] virtual_address;
|
||||
|
@ -147,14 +147,14 @@ interface mmu_interface;
|
|||
logic is_fault;
|
||||
|
||||
//From CSR
|
||||
logic [21:0] ppn;
|
||||
logic [21:0] satp_ppn;
|
||||
logic mxr; //Make eXecutable Readable
|
||||
logic sum; //permit Supervisor User Memory access
|
||||
logic [1:0] privilege;
|
||||
|
||||
modport mmu (input virtual_address, new_request, execute, rnw, ppn, mxr, sum, privilege, output write_entry, upper_physical_address, is_fault);
|
||||
modport tlb (input write_entry, upper_physical_address, is_fault, output new_request, virtual_address, execute, rnw);
|
||||
modport csr (output ppn, mxr, sum, privilege);
|
||||
modport mmu (input virtual_address, request, execute, rnw, satp_ppn, mxr, sum, privilege, output write_entry, upper_physical_address, is_fault);
|
||||
modport tlb (input write_entry, upper_physical_address, is_fault, output request, virtual_address, execute, rnw);
|
||||
modport csr (output satp_ppn, mxr, sum, privilege);
|
||||
|
||||
endinterface
|
||||
|
||||
|
|
62
core/mmu.sv
62
core/mmu.sv
|
@ -30,6 +30,7 @@ module mmu
|
|||
input logic clk,
|
||||
input logic rst,
|
||||
mmu_interface.mmu mmu,
|
||||
input logic abort_request,
|
||||
l1_arbiter_request_interface.master l1_request,
|
||||
l1_arbiter_return_interface.master l1_response
|
||||
);
|
||||
|
@ -63,6 +64,10 @@ module mmu
|
|||
pte_t pte;
|
||||
logic access_valid;
|
||||
logic privilege_valid;
|
||||
|
||||
localparam MAX_ABORTED_REQUESTS = 4;
|
||||
logic abort_queue_full;
|
||||
logic discard_data;
|
||||
////////////////////////////////////////////////////
|
||||
//Implementation
|
||||
|
||||
|
@ -74,13 +79,13 @@ module mmu
|
|||
assign l1_request.is_amo = 0;
|
||||
assign l1_request.amo = 0;
|
||||
|
||||
assign l1_request.request = state[SEND_REQUEST_1] | state[SEND_REQUEST_2];
|
||||
assign l1_request.request = (state[SEND_REQUEST_1] | state[SEND_REQUEST_2]) & ~abort_request;
|
||||
|
||||
//Page Table addresses
|
||||
always_ff @ (posedge clk) begin
|
||||
if (state[IDLE] | l1_response.data_valid) begin
|
||||
if (state[IDLE])
|
||||
l1_request.addr <= {mmu.ppn[19:0], mmu.virtual_address[31:22], 2'b00};
|
||||
l1_request.addr <= {mmu.satp_ppn[19:0], mmu.virtual_address[31:22], 2'b00};
|
||||
else
|
||||
l1_request.addr <= {{pte.ppn1[9:0], pte.ppn0}, mmu.virtual_address[21:12], 2'b00};
|
||||
end
|
||||
|
@ -88,6 +93,25 @@ module mmu
|
|||
|
||||
assign pte = l1_response.data;
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//Supports unlimited tracking of aborted requests
|
||||
//Assumption: memory requests are returned in-order
|
||||
localparam COUNT_W = $clog2(MAX_ABORTED_REQUESTS);
|
||||
logic [COUNT_W:0] abort_tracking;
|
||||
logic delayed_abort;
|
||||
logic delayed_abort_complete;
|
||||
|
||||
assign delayed_abort = abort_request & (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2]);
|
||||
assign delayed_abort_complete = discard_data & l1_response.data_valid;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
abort_tracking <= 0;
|
||||
else
|
||||
abort_tracking <= abort_tracking - COUNT_W'(delayed_abort) + COUNT_W'(delayed_abort_complete);
|
||||
end
|
||||
|
||||
assign discard_data = abort_tracking[COUNT_W];
|
||||
assign abort_queue_full = abort_tracking[COUNT_W] & ~|abort_tracking[COUNT_W-1:0];
|
||||
////////////////////////////////////////////////////
|
||||
//Access and permission checks
|
||||
//A and D bits are software managed
|
||||
|
@ -107,15 +131,13 @@ module mmu
|
|||
next_state = state;
|
||||
case (1'b1)
|
||||
state[IDLE] :
|
||||
if (mmu.new_request) begin
|
||||
if (mmu.request & ~abort_queue_full)
|
||||
next_state = 2**SEND_REQUEST_1;
|
||||
end
|
||||
state[SEND_REQUEST_1] :
|
||||
if (l1_request.ack) begin
|
||||
if (l1_request.ack)
|
||||
next_state = 2**WAIT_REQUEST_1;
|
||||
end
|
||||
state[WAIT_REQUEST_1] :
|
||||
if (l1_response.data_valid) begin
|
||||
if (l1_response.data_valid & ~discard_data) begin
|
||||
if (~pte.v | (~pte.r & pte.w)) //page not valid OR invalid xwr pattern
|
||||
next_state = 2**COMPLETE_FAULT;
|
||||
else if (pte.v & (pte.r | pte.x)) begin//superpage (all remaining xwr patterns other than all zeros)
|
||||
|
@ -123,16 +145,14 @@ module mmu
|
|||
next_state = 2**COMPLETE_SUCCESS;
|
||||
else
|
||||
next_state = 2**COMPLETE_FAULT;
|
||||
end
|
||||
else //(pte.v & ~pte.x & ~pte.w & ~pte.r) pointer to next level in page table
|
||||
end else //(pte.v & ~pte.x & ~pte.w & ~pte.r) pointer to next level in page table
|
||||
next_state = 2**SEND_REQUEST_2;
|
||||
end
|
||||
state[SEND_REQUEST_2] :
|
||||
if (l1_request.ack) begin
|
||||
if (l1_request.ack)
|
||||
next_state = 2**WAIT_REQUEST_2;
|
||||
end
|
||||
state[WAIT_REQUEST_2] :
|
||||
if (l1_response.data_valid) begin
|
||||
if (l1_response.data_valid & ~discard_data) begin
|
||||
if (access_valid & privilege_valid)
|
||||
next_state = 2**COMPLETE_SUCCESS;
|
||||
else
|
||||
|
@ -141,6 +161,9 @@ module mmu
|
|||
state[COMPLETE_SUCCESS], state[COMPLETE_FAULT] :
|
||||
next_state = 2**IDLE;
|
||||
endcase
|
||||
//If request is aborted, return to IDLE
|
||||
if (abort_request)
|
||||
next_state = 2**IDLE;
|
||||
end
|
||||
|
||||
always_ff @ (posedge clk) begin
|
||||
|
@ -167,8 +190,17 @@ module mmu
|
|||
|
||||
////////////////////////////////////////////////////
|
||||
//Assertions
|
||||
mmu_spurious_l1_response:
|
||||
assert property (@(posedge clk) disable iff (rst) (l1_response.data_valid) |-> (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2]))
|
||||
else $error("mmu recieved response without a request");
|
||||
`ifdef ENABLE_SIMULATION_ASSERTIONS
|
||||
mmu_spurious_l1_response:
|
||||
assert property (@(posedge clk) disable iff (rst) (l1_response.data_valid) |-> (state[WAIT_REQUEST_1] | state[WAIT_REQUEST_2]))
|
||||
else $error("mmu recieved response without a request");
|
||||
`endif
|
||||
|
||||
//TLB request remains high until it recieves a response from the MMU unless
|
||||
//the transaction is aborted. As such, if TLB request is low and we are not in the
|
||||
//IDLE state, then our current processor state has been corrupted
|
||||
mmu_tlb_state_mismatch:
|
||||
assert property (@(posedge clk) disable iff (rst) (~mmu.request) |-> (state[IDLE]))
|
||||
else $error("MMU and TLB state mismatch");
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -300,6 +300,7 @@ module taiga (
|
|||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (immu) ,
|
||||
.abort_request (gc_fetch_flush),
|
||||
.l1_request (l1_request[L1_IMMU_ID]),
|
||||
.l1_response (l1_response[L1_IMMU_ID])
|
||||
);
|
||||
|
@ -456,6 +457,7 @@ module taiga (
|
|||
.clk (clk),
|
||||
.rst (rst),
|
||||
.mmu (dmmu) ,
|
||||
.abort_request (1'b0),
|
||||
.l1_request (l1_request[L1_DMMU_ID]),
|
||||
.l1_response (l1_response[L1_DMMU_ID])
|
||||
);
|
||||
|
|
|
@ -28,8 +28,9 @@ package taiga_types;
|
|||
|
||||
localparam WB_UNITS_WIDTH = $clog2(NUM_WB_UNITS);
|
||||
localparam LOG2_COMMIT_PORTS = $clog2(COMMIT_PORTS);
|
||||
localparam LOG2_MAX_IDS = $clog2(MAX_IDS);
|
||||
|
||||
typedef logic[$clog2(MAX_IDS)-1:0] id_t;
|
||||
typedef logic[LOG2_MAX_IDS-1:0] id_t;
|
||||
typedef logic[WB_UNITS_WIDTH-1:0] unit_id_t;
|
||||
typedef logic[1:0] branch_predictor_metadata_t;
|
||||
|
||||
|
|
|
@ -114,11 +114,11 @@ module tlb_lut_ram #(
|
|||
|
||||
always_ff @ (posedge clk) begin
|
||||
if (rst)
|
||||
mmu.new_request <= 0;
|
||||
else if (mmu.write_entry)
|
||||
mmu.new_request <= 0;
|
||||
mmu.request <= 0;
|
||||
else if (mmu.write_entry | mmu.is_fault)
|
||||
mmu.request <= 0;
|
||||
else if (tlb_on & ~hit & tlb.new_request)
|
||||
mmu.new_request <= 1;
|
||||
mmu.request <= 1;
|
||||
end
|
||||
|
||||
assign mmu.virtual_address = tlb.virtual_address;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue