mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-23 05:37:16 -04:00
Remove latch from fetch FSM
This commit is contained in:
parent
64a46d5a97
commit
56c8086456
5 changed files with 41 additions and 37 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
16
src/mmu.sv
16
src/mmu.sv
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
52
src/ptw.sv
52
src/ptw.sv
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue