blob: d92b930194afff61c5dfae288235a7491c3f92fe [file] [log] [blame]
`include "../params.vh"
module ptw
# (
parameter PTE_SIZE = 8,
parameter PTE_SIZE_IN_BIT = 64,
parameter VIRTUAL_ADDR_LEN_SV39 = 39,
parameter PHYSICAL_ADDR_LEN_SV39 = 56,
parameter PAGE_OFFSET_WIDTH = 12,
parameter VPN_SLICE_WIDTH = 9
)
(
input ptw_enable_i,
input [1:0] page_table_level_i,
input [VIRTUAL_ADDR_LEN_SV39 - 1 : 0] virtual_address_i,
input pte_active_i,
input [PTE_SIZE_IN_BIT - 1 : 0] pte_i,
input [SATP_PPN_WIDTH - 1 : 0] satp_ppn_i,
output pte_is_leaf_o,
output req_next_level_pte_o,
output [PHYSICAL_ADDR_LEN_SV39 - 1 : 0] pte_req_address_o,
output page_fault_valid_o
);
reg pte_is_leaf;
reg req_next_level_pte;
reg [PHYSICAL_ADDR_LEN_SV39 - 1 : 0] pte_req_address;
reg [VPN_SLICE_WIDTH - 1: 0] pte_req_index;
reg page_fault_valid;
assign pte_is_leaf_o = pte_is_leaf;
assign req_next_level_pte_o = req_next_level_pte;
assign pte_req_address_o = pte_req_address;
assign page_fault_valid_o = page_fault_valid;
always @(*) begin
if (ptw_enable_i) begin
case (page_table_level_i)
2'b10: pte_req_index = virtual_address_i[`va_vpn2];
2'b01: pte_req_index = virtual_address_i[`va_vpn1];
2'b00: pte_req_index = virtual_address_i[`va_vpn0];
default: page_fault_valid = 1'b1;
endcase
if (pte_active_i) begin
pte_req_address = ({12'h000,pte_i[`pte_ppn]} << PAGE_OFFSET_WIDTH) + pte_req_index * PTE_SIZE;
// Step 4: Leaf/Non-leaf pte check
casez ({pte_i[`pte_x],pte_i[`pte_w],pte_i[`pte_r],pte_i[`pte_v]})
// pte.v = 0 ==> page fault
4'b???0: begin
pte_is_leaf = 1'b0;
req_next_level_pte = 1'b0;
page_fault_valid = 1'b1;
end
// pte.r = 0 and pte.w = 1 ==> page fault
4'b?101: begin
pte_is_leaf = 1'b0;
req_next_level_pte = 1'b0;
page_fault_valid = 1'b1;
end
// pte.x = 1 ==> leaf pte
// @TODO: x-only pte is for I-TLB
4'b1001: begin
pte_is_leaf = 1'b1;
req_next_level_pte = 1'b0;
page_fault_valid = 1'b0;
end
// pte.r = 1 ==> leaf pte
4'b??11: begin
pte_is_leaf = 1'b1;
req_next_level_pte = 1'b0;
page_fault_valid = 1'b0;
end
// default ==> request next level pte
default: begin
pte_is_leaf = 1'b0;
req_next_level_pte = 1'b1;
page_fault_valid = 1'b0;
end
endcase
end else begin
pte_is_leaf = 1'b0;
req_next_level_pte = 1'b1;
pte_req_address = ({12'h000,satp_ppn_i} << PAGE_OFFSET_WIDTH) + pte_req_index * PTE_SIZE;
page_fault_valid = 1'b0;
end
end else begin
pte_is_leaf = 1'b0;
req_next_level_pte = 1'b0;
pte_req_address = '0;
page_fault_valid = 1'b0;
end
end
endmodule