added support to abort MMU requests

This commit is contained in:
Eric Matthews 2020-08-18 14:08:30 -07:00
parent 02d51444d4
commit f501c938f4
7 changed files with 73 additions and 32 deletions

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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])
);

View file

@ -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;

View file

@ -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;