Remove latch from fetch FSM

This commit is contained in:
Florian Zaruba 2017-06-17 13:07:06 +02:00
parent 64a46d5a97
commit 56c8086456
5 changed files with 41 additions and 37 deletions

View file

@ -149,7 +149,7 @@ module commit_stage (
STORE_PAGE_FAULT: cause = "Store Page Fault";
default: cause = "Interrupt";
endcase
$display("Exception @%t, PC: %0h, TVal: %0h, Cause: %s", $time, commit_instr_i.pc, exception_o.tval, cause);
$display("Exception @%t, PC: %h, TVal: %h, Cause: %s", $time, commit_instr_i.pc, exception_o.tval, cause);
end
end
`endif

View file

@ -57,7 +57,7 @@ module if_stage (
//---------------------------------
// we are busy if we are either waiting for a grant
// or if the FIFO is full
assign if_busy_o = ((CS == WAIT_GNT) && !instr_req_o) || !fifo_ready;
assign if_busy_o = (CS == WAIT_GNT) || !fifo_ready;
assign fetch_address = {fetch_address_i[63:2], 2'b0};
//---------------------------------
@ -86,6 +86,7 @@ module if_stage (
instr_addr_o = fetch_address;
fifo_valid = 1'b0;
NS = CS;
addr_valid = 1'b0;
unique case(CS)
// default state, not waiting for requested data
@ -99,7 +100,7 @@ module if_stage (
addr_valid = 1'b1;
if(instr_gnt_i) //~> granted request
if (instr_gnt_i) //~> granted request
// we have one outstanding rvalid: wait for it
if (flush_i)
NS = WAIT_ABORTED;
@ -183,6 +184,7 @@ module if_stage (
// we can do a new request here, we won't get a grant until the rvalid came back for the
// request we sent to end in here
instr_addr_o = fetch_address;
addr_valid = 1'b1;
// we are aborting this instruction so don't tell the FIFO it is valid
fifo_valid = 1'b0;
// check if the fetch is valid before making a new request

View file

@ -91,7 +91,7 @@ module mmu #(
logic update_is_2M;
logic update_is_1G;
logic [26:0] update_vpn;
logic [38:0] update_vaddr;
logic [0:0] update_asid;
pte_t update_content;
@ -124,7 +124,7 @@ module mmu #(
.flush_i ( flush_tlb_i ),
.update_is_2M_i ( update_is_2M ),
.update_is_1G_i ( update_is_1G ),
.update_vpn_i ( update_vpn ),
.update_vpn_i ( update_vaddr[38:12] ),
.update_asid_i ( update_asid ),
.update_content_i ( update_content ),
.update_tlb_i ( itlb_update ),
@ -147,7 +147,7 @@ module mmu #(
.flush_i ( flush_tlb_i ),
.update_is_2M_i ( update_is_2M ),
.update_is_1G_i ( update_is_1G ),
.update_vpn_i ( update_vpn ),
.update_vpn_i ( update_vaddr[38:12] ),
.update_asid_i ( update_asid ),
.update_content_i ( update_content ),
.update_tlb_i ( dtlb_update ),
@ -179,7 +179,7 @@ module mmu #(
.update_content_o ( update_content ),
.update_is_2M_o ( update_is_2M ),
.update_is_1G_o ( update_is_1G ),
.update_vpn_o ( update_vpn ),
.update_vaddr_o ( update_vaddr ),
.update_asid_o ( update_asid ),
.itlb_access_i ( itlb_lu_access ),
@ -243,7 +243,7 @@ module mmu #(
fetch_gnt_o = 1'b1;
ierr_valid_n = 1'b1;
// throw a page fault
fetch_ex_n = {INSTR_PAGE_FAULT, fetch_vaddr_i, 1'b1};
fetch_ex_n = {INSTR_ACCESS_FAULT, fetch_vaddr_i, 1'b1};
end
end else
// ---------
@ -254,7 +254,7 @@ module mmu #(
// on an error pass through fetch with an error signaled
fetch_gnt_o = ptw_error;
ierr_valid_n = ptw_error; // signal valid/error on next cycle
fetch_ex_n = {INSTR_ACCESS_FAULT, fetch_vaddr_i, 1'b1};
fetch_ex_n = {INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
end
end
// the fetch is valid if we either got an error in the previous cycle or the I$ gave us a valid signal.
@ -313,9 +313,9 @@ module mmu #(
lsu_valid_o = 1'b1;
// the page table walker can only throw page faults
if (lsu_is_store_i) begin
lsu_exception_o = {STORE_PAGE_FAULT, lsu_vaddr_i, 1'b1};
lsu_exception_o = {STORE_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
end else begin
lsu_exception_o = {LOAD_PAGE_FAULT, lsu_vaddr_i, 1'b1};
lsu_exception_o = {LOAD_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1};
end
end
end

View file

@ -79,7 +79,7 @@ module pcgen (
// -------------------------------
// default is a consecutive PC
if (if_ready_i && fetch_enable_i)
npc_n = {npc_q[62:2], 2'b0} + 64'h4;
npc_n = {npc_q[63:2], 2'b0} + 64'h4;
else // or keep the PC stable if IF is not ready
npc_n = npc_q;
// we only need to stall the consecutive and predicted case since in any other case we will flush at least

View file

@ -53,7 +53,7 @@ module ptw #(
output logic update_is_2M_o,
output logic update_is_1G_o,
output logic [26:0] update_vpn_o,
output logic [38:0] update_vaddr_o,
output logic [ASID_WIDTH-1:0] update_asid_o,
input logic [ASID_WIDTH-1:0] asid_i,
// from TLBs
@ -90,22 +90,19 @@ module ptw #(
logic is_instr_ptw_q, is_instr_ptw_n;
logic global_mapping_q, global_mapping_n;
// latched tag signal
logic tag_valid_n, tag_valid_q;
logic tag_valid_n, tag_valid_q;
// register the ASID
logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n;
// register the VPN we need to walk, SV39 defines a 39 bit virtual address
logic [38:0] vaddr_q, vaddr_n;
// 4 byte aligned physical pointer
logic[55:0] ptw_pptr_q, ptw_pptr_n;
// Assignments
assign update_vaddr_o = vaddr_q;
assign ptw_active_o = (ptw_state_q != PTW_READY);
assign walking_instr_o = is_instr_ptw_q;
// register the ASID
logic [ASID_WIDTH-1:0] tlb_update_asid_q, tlb_update_asid_n;
// register the VPN we need to walk
logic [26:0] tlb_update_vpn_q, tlb_update_vpn_n;
// 4 byte aligned physical pointer
logic[55:0] ptw_pptr_q, ptw_pptr_n;
// directly output the correct physical address
// ------
// TODO
// -------
// assign address_o = {ptw_pptr_q, 4'b0}; TODO
assign address_index_o = ptw_pptr_q[11:0];
assign address_tag_o = ptw_pptr_q[55:12];
// we are never going to kill this request
@ -115,8 +112,7 @@ module ptw #(
// update the correct page table level
assign update_is_2M_o = (ptw_lvl_q == LVL2);
assign update_is_1G_o = (ptw_lvl_q == LVL1);
// output the correct VPN and ASID
assign update_vpn_o = tlb_update_vpn_q;
// output the correct ASID
assign update_asid_o = tlb_update_asid_q;
// set the global mapping bit
assign update_content_o = pte || (global_mapping_q << 5);
@ -162,25 +158,28 @@ module ptw #(
global_mapping_n = global_mapping_q;
// input registers
tlb_update_asid_n = tlb_update_asid_q;
tlb_update_vpn_n = tlb_update_vpn_q;
vaddr_n = vaddr_q;
case (ptw_state_q)
PTW_READY: begin
// by default we start with the top-most page table
ptw_lvl_n = LVL1;
global_mapping_n = 1'b0;
// if we got an ITLB miss
if (enable_translation_i & itlb_access_i & itlb_miss_i & ~dtlb_access_i) begin
ptw_pptr_n = {satp_ppn_i, itlb_vaddr_i[38:30], 3'b0};
is_instr_ptw_n = 1'b1;
tlb_update_asid_n = asid_i;
tlb_update_vpn_n = itlb_vaddr_i[38:12];
vaddr_n = itlb_vaddr_i;
ptw_state_n = PTW_WAIT_GRANT;
// we got an DTLB miss
end else if (enable_translation_i & dtlb_access_i & dtlb_miss_i) begin
ptw_pptr_n = {satp_ppn_i, dtlb_vaddr_i[38:30], 3'b0};
is_instr_ptw_n = 1'b0;
tlb_update_asid_n = asid_i;
tlb_update_vpn_n = dtlb_vaddr_i[38:12];
vaddr_n = dtlb_vaddr_i;
ptw_state_n = PTW_WAIT_GRANT;
end
end
@ -188,6 +187,14 @@ module ptw #(
PTW_WAIT_GRANT: begin
// send a request out
data_req_o = 1'b1;
// depending on the current level send the right address
if (ptw_lvl_q == LVL2)
ptw_pptr_n = {pte.ppn, vaddr_q[29:21], 3'b0};
if (ptw_lvl_q == LVL3)
ptw_pptr_n = {pte.ppn, vaddr_q[20:12], 3'b0};
// wait for the grant
if (data_gnt_i) begin
// send the tag valid signal one cycle later
@ -202,11 +209,6 @@ module ptw #(
// check if the global mapping bit is set
if (pte.g)
global_mapping_n = 1'b1;
// depending on the current level send the right address
if (ptw_lvl_q == LVL2)
ptw_pptr_n = {pte.ppn, tlb_update_vpn_q[17:9], 3'b0};
if (ptw_lvl_q == LVL3)
ptw_pptr_n = {pte.ppn, tlb_update_vpn_q[8:0], 3'b0};
// -------------
// Invalid PTE
@ -294,7 +296,7 @@ module ptw #(
ptw_lvl_q <= LVL1;
tag_valid_q <= 1'b0;
tlb_update_asid_q <= '{default: 0};
tlb_update_vpn_q <= '{default: 0};
vaddr_q <= '0;
ptw_pptr_q <= '{default: 0};
global_mapping_q <= 1'b0;
end else begin
@ -304,7 +306,7 @@ module ptw #(
ptw_lvl_q <= ptw_lvl_n;
tag_valid_q <= tag_valid_n;
tlb_update_asid_q <= tlb_update_asid_n;
tlb_update_vpn_q <= tlb_update_vpn_n;
vaddr_q <= vaddr_n;
global_mapping_q <= global_mapping_n;
end
end