diff --git a/sim/config.vlt b/sim/config.vlt index 728db32..d06dcb2 100644 --- a/sim/config.vlt +++ b/sim/config.vlt @@ -1,9 +1,11 @@ `verilator_config lint_off -rule TIMESCALEMOD lint_off -rule DECLFILENAME +lint_off -rule INITIALDLY lint_off -file "model/*.v" lint_off -file "../resources/func_test/*.v" -lint_off -rule BLKSEQ -file "../src/CP0/CP0.sv" -lint_off -rule PINCONNECTEMPTY -file "../src/MU/MU.sv" +lint_off -rule UNOPTFLAT -file "model/axi_crossbar_addr.v" +lint_off -rule UNOPTFLAT -file "model/priority_encoder.v" +lint_off -rule BLKSEQ -file "../src/CP0/CP0.sv" diff --git a/src/Core/Datapath.sv b/src/Core/Datapath.sv index ff92386..7c55b25 100644 --- a/src/Core/Datapath.sv +++ b/src/Core/Datapath.sv @@ -1232,10 +1232,10 @@ module Datapath ( assign C0_wdata = M_I0_ForwardT; // M.I1.MEM - assign C0.cpu_tlbwi = M.I1.MCtrl.TLBWI; - assign C0.cpu_tlbwr = M.I1.MCtrl.TLBWR; - assign C0.cpu_tlbr = M.I1.MCtrl.TLBR; - assign C0.cpu_c0_tlbp = M.I1.MCtrl.TLBP & M.en; + assign C0.cpu_tlbwi = M.I1.MCtrl.TLBWI; + assign C0.cpu_tlbwr = M.I1.MCtrl.TLBWR; + assign C0.cpu_tlbr = M.I1.MCtrl.TLBR; + assign C0.cpu_c0_tlbp = M.I1.MCtrl.TLBP & M.en; assign mem.wr = M.I1.MCtrl.MWR; memoutput M_I1_memoutput ( .addr (M.I1.ALUOut[1:0]), diff --git a/src/MU/MU.sv b/src/MU/MU.sv index 3ebd66d..7ed0a92 100644 --- a/src/MU/MU.sv +++ b/src/MU/MU.sv @@ -20,6 +20,7 @@ module MU ( // == CacheOp == // ============= + // NOTE: req and op and addr should be kept until addr_ok logic cop_i_req = cacheop.req & cacheop.op.icache_op; logic cop_d_req = cacheop.req & cacheop.op.dcache_op; logic cop_i_ok, cop_d_ok; @@ -51,10 +52,8 @@ module MU ( // TLB word_t instfetch_phy_addr; - logic instfetch_hit; logic instfetch_cached; logic instfetch_valid; - logic instfetch_privilege; // =============== // AXI Read Worker @@ -158,6 +157,9 @@ module MU ( cacheop.addr_ok = 1; icache.index_for_lookup = cacheop.addr[`IC_TAGL-1:`IC_INDEXL]; + end else if (~instfetch_valid) begin + in_if_ready = 1; + end else if (if_req & instfetch_cached & icache.hit) begin // Cached + Hit -> return ifc_next_state = IFC_LOOKUP; @@ -230,6 +232,7 @@ module MU ( icache.ctrl.cache_index_invalidate = ~stored_cacheop_op.index_or_hit; icache.ctrl.cache_hit_invalidate = stored_cacheop_op.index_or_hit; + icache.index = stored_cacheop_addr[`IC_TAGL-1:`IC_INDEXL]; icache.index_for_lookup = stored_cacheop_addr[`IC_TAGL-1:`IC_INDEXL]; end default: begin end @@ -419,6 +422,9 @@ module MU ( // Handle Cache Instruction mem_nxt_state = MEM_CACHE_INVALID; dcache.index_for_lookup = cacheop.addr[`DC_TAGL-1:`DC_INDEXL]; + end else if (~memory_valid) begin + in_mem_ready = 1; + end else if (mem_req & memory_cached & dcache.hit) begin // Cached + Hit if (~memory.wr) begin @@ -605,6 +611,82 @@ module MU ( // ======= virt addr -> phy addr ======= // ===================================== +`ifdef ENABLE_TLB + + logic tlbw; + logic [2:0] c0_Index_u; + + assign tlbw = cp0.cpu_tlbwi | cp0.cpu_tlbwr; + assign c0_Index_u = cp0.cpu_tlbwr ? cp0.cp0_Random[2:0] : cp0.cp0_Index[2:0]; + + word_t iVA, iPA1; + word_t dVA, dPA1; + logic iHit1, iCached1, iMValid1, iUser1; + logic dHit1, dCached1, dMValid1, dUser1, dDirty1; + + TLB TLB ( + .clk (clk), + .rst (rst), + .K0 (cp0.cp0_K0), + .tlbw (tlbw), + .tlbp (cp0.cpu_tlb_tlbp), + .c0_Index (c0_Index_u), + .c0_EntryHi (cp0.cp0_EntryHi), + .c0_EntryLo1(cp0.cp0_EntryLo1), + .c0_EntryLo0(cp0.cp0_EntryLo0), + .EntryHi (cp0.tlb_EntryHi), + .EntryLo1 (cp0.tlb_EntryLo1), + .EntryLo0 (cp0.tlb_EntryLo0), + .Index (cp0.tlb_Index), + + .iVAddr (iVA), + .iPAddr (iPA1), + .iHit (iHit1), + .iCached (iCached1), + .iValid (iMValid1), + .iUser (iUser1), + .dVAddr (dVA), + .dPAddr (dPA1), + .dHit (dHit1), + .dCached (dCached1), + .dDirty (dDirty1), + .dValid (dMValid1), + .dUser (dUser1) + ); + + logic choose_cop_i = (ifc_cur_state == IFC_LOOKUP) & cop_i_req; + logic choose_cop_d = (mem_cur_state == MEM_LOOKUP) & cop_d_req; + + // instfetch + assign iVA = choose_cop_i ? cacheop.addr : (instfetch.req ? instfetch.addr : stored_instfetch_addr); + assign instfetch_phy_addr = iPA1; + assign instfetch_valid = iHit1 & iMValid1 & (cp0.cp0_in_kernel | iUser1); + assign instfetch_cached = iCached1; + + assign cp0.tlb_iTLBRefill = if_req & ~iHit1; + assign cp0.tlb_iTLBInvalid = if_req & ~iMValid1; + assign cp0.tlb_iAddressError = if_req & ~(cp0.cp0_in_kernel | iUser1); + + // memory + assign dVA = choose_cop_d ? cacheop.addr : (memory.req ? memory.addr : stored_memory_addr); + assign memory_phy_addr = dPA1; + // TODO: should memory.wr be stored? + assign memory_valid = dHit1 & dMValid1 & (cp0.cp0_in_kernel | dUser1) & (~memory.wr | dDirty1); + assign memory_cached = dCached1; + + assign cp0.tlb_dTLBRefill = mem_req & ~dHit1; + assign cp0.tlb_dTLBInvalid = mem_req & ~dMValid1; + assign cp0.tlb_dTLBModified = mem_req & memory.wr & ~dDirty1; + assign cp0.tlb_dAddressError = mem_req & ~(cp0.cp0_in_kernel | dUser1); + +`else + + logic if_vp_hit, if_vp_valid, if_vp_privilege; + logic mem_vp_hit, mem_vp_valid, mem_vp_privilege; + assign instfetch_valid = if_vp_hit & if_vp_valid; + assign memory_valid = mem_vp_hit & mem_vp_valid; + + /* verilator lint_off PINCONNECTEMPTY */ addr_virt_to_phy instfetch_addr_convert( .K0 (cp0.cp0_K0), .virt_addr (stored_instfetch_addr), @@ -614,11 +696,11 @@ module MU ( .tlb_dirty (1'b1), .tlb_valid (1'b1), .phy_addr (instfetch_phy_addr), - .hit (instfetch_hit), + .hit (if_vp_hit), .cached (instfetch_cached), .dirty (), - .valid (instfetch_valid), - .privilege (instfetch_privilege) + .valid (if_vp_valid), + .privilege (if_vp_privilege) ); addr_virt_to_phy memory_addr_convert( .K0 (cp0.cp0_K0), @@ -629,12 +711,26 @@ module MU ( .tlb_dirty (1'b1), .tlb_valid (1'b1), .phy_addr (memory_phy_addr), - .hit (memory_hit), + .hit (mem_vp_hit), .cached (memory_cached), - .dirty (memory_dirty), - .valid (memory_valid), - .privilege (memory_privilege) + .dirty (), + .valid (mem_vp_valid), + .privilege (mem_vp_privilege) ); + /* verilator lint_on PINCONNECTEMPTY */ + assign cp0.tlb_EntryHi = 0; + assign cp0.tlb_EntryLo1 = 0; + assign cp0.tlb_EntryLo0 = 0; + assign cp0.tlb_Index = 0; + assign cp0.tlb_iTLBRefill = 0; + assign cp0.tlb_iTLBInvalid = 0; + assign cp0.tlb_iAddressError = 0; + assign cp0.tlb_dTLBRefill = 0; + assign cp0.tlb_dTLBInvalid = 0; + assign cp0.tlb_dTLBModified = 0; + assign cp0.tlb_dAddressError = 0; + +`endif endmodule diff --git a/src/MU/TLB.sv b/src/MU/TLB.sv index e78e46c..8842dd6 100644 --- a/src/MU/TLB.sv +++ b/src/MU/TLB.sv @@ -12,12 +12,10 @@ module TLB ( input logic [2:0] c0_Index, // TLBWR + TLBWI + TLBR input EntryHi_t c0_EntryHi, // TLBWI + F/M(ASID) - // input PageMask_t c0_PageMask, // TLBWI input EntryLo_t c0_EntryLo1, // TLBWI input EntryLo_t c0_EntryLo0, // TLBWI output EntryHi_t EntryHi, // TLBR - // output PageMask_t PageMask, // TLBR output EntryLo_t EntryLo1, // TLBR output EntryLo_t EntryLo0, // TLBR output Index_t Index, // TLBP @@ -57,28 +55,25 @@ module TLB ( TLB_t [7:0] TLB_entries; TLB_t entry; - // CP0(TLBWI) EntryHi /*PageMask*/ EntryLo0 EntryLo1 -> TLB[Index] + // CP0(TLBWI) EntryHi EntryLo0 EntryLo1 -> TLB[Index] always_ff @(posedge clk) begin if (rst) begin TLB_entries <= 624'b0; end else if (tlbw) - TLB_entries[c0_Index] <= {c0_EntryHi.VPN2, c0_EntryHi.ASID, - // c0_PageMask.Mask, - c0_EntryLo0.G & c0_EntryLo1.G, - c0_EntryLo0.PFN, c0_EntryLo0.C, c0_EntryLo0.D, c0_EntryLo0.V, - c0_EntryLo1.PFN, c0_EntryLo1.C, c0_EntryLo1.D, c0_EntryLo1.V}; + TLB_entries[c0_Index] <= { + c0_EntryHi.VPN2, c0_EntryHi.ASID, + c0_EntryLo0.G & c0_EntryLo1.G, + c0_EntryLo0.PFN, c0_EntryLo0.C, c0_EntryLo0.D, c0_EntryLo0.V, + c0_EntryLo1.PFN, c0_EntryLo1.C, c0_EntryLo1.D, c0_EntryLo1.V + }; end - // CP0(TLBR) Index -> EntryHi /*PageMask*/ EntryLo0 EntryLo1 + // CP0(TLBR) Index -> EntryHi EntryLo0 EntryLo1 assign entry = TLB_entries[c0_Index]; assign EntryHi.zero = 5'b0; assign EntryHi.VPN2 = entry.VPN2; assign EntryHi.ASID = entry.ASID; - // assign PageMask.zero1 = 7'b0; - // assign PageMask.Mask = entry.PageMask; - // assign PageMask.zero2 = 13'b0; - assign EntryLo0.zero = 6'b0; assign EntryLo0.PFN = entry.PFN0; assign EntryLo0.C = entry.C0; @@ -135,57 +130,37 @@ module TLB ( // Output ffenr #(55) inst_ff( - clk, rst, - {fVAddr, fPAddr, fHit, fCached, fValid}, - 1'b1, - {fVAddr1, fPAddr1, fHit1, fCached1, fValid1} + .*, + .d ({fVAddr, fPAddr, fHit, fCached, fValid}), + .en(1'b1), + .q ({fVAddr1, fPAddr1, fHit1, fCached1, fValid1}) ); - always_comb begin - if (fVAddr1 > 32'hBFFF_FFFF || fVAddr1 <= 32'h7FFF_FFFF) begin - // kseg2 + kseg3 + kuseg -> tlb - iPAddr = {fPAddr1, fVAddr1[11:0]}; - iHit = fHit1; - iCached = fCached1; - iValid = fValid1; - iUser = ~fVAddr1[31]; - end else if (fVAddr1 > 32'h9FFF_FFFF) begin - // kseg1 uncached - iPAddr = fVAddr1 & 32'h1FFF_FFFF; - iHit = 1'b1; - iCached = 1'b0; - iValid = 1'b1; - iUser = 1'b0; - end else begin - // kseg0 -> CP0.K0 - iPAddr = fVAddr1 & 32'h1FFF_FFFF; - iHit = 1'b1; - iCached = K0[0]; - iValid = 1'b1; - iUser = 1'b0; - end - end + /* verilator lint_off PINCONNECTEMPTY */ addr_virt_to_phy instfetch_addr_convert( + .K0 (K0), .virt_addr (fVAddr1), .tlb_addr (fPAddr1), .tlb_hit (fHit1), .tlb_cached (fCached1), - .tlb_dirty (fDirty1), + .tlb_dirty (), .tlb_valid (fValid1), .phy_addr (iPAddr), .hit (iHit), .cached (iCached), - .dirty (iDirty), + .dirty (), .valid (iValid), .privilege (iUser) // not ); + /* verilator lint_on PINCONNECTEMPTY */ ffenr #(56) data_ff ( - clk, rst, - {mVAddr, mPAddr, mHit, mCached, mValid, mDirty}, - 1'b1, - {mVAddr1, mPAddr1, mHit1, mCached1, mValid1, mDirty1} + .*, + .d ({mVAddr, mPAddr, mHit, mCached, mValid, mDirty}), + .en(1'b1), + .q ({mVAddr1, mPAddr1, mHit1, mCached1, mValid1, mDirty1}) ); addr_virt_to_phy memory_addr_convert( + .K0 (K0), .virt_addr (mVAddr1), .tlb_addr (mPAddr1), .tlb_hit (mHit1), diff --git a/src/MU/TLB_Lookup.sv b/src/MU/TLB_Lookup.sv index 967b974..ac5ebee 100644 --- a/src/MU/TLB_Lookup.sv +++ b/src/MU/TLB_Lookup.sv @@ -16,18 +16,14 @@ module TLB_Lookup ( logic [7:0] hitWay; for (genvar i = 0; i < 8; i++) - // assign hitWay[i] = ((TLB_entries[i].VPN2 & ~{7'b0, TLB_entries[i].PageMask}) - // == (VPN[19:1] & ~{7'b0, TLB_entries[i].PageMask})) - // & (TLB_entries[i].G | TLB_entries[i].ASID == ASID); assign hitWay[i] = (TLB_entries[i].VPN2 == VPN[19:1]) & (TLB_entries[i].G | TLB_entries[i].ASID == ASID); - // assume: hit is unique + // NOTE: assume: hit is unique assign hit = |{hitWay}; assign index.P = ~hit; assign index.zero = 0; onehot_bin8 index_decoder(hitWay, index.Index); - // always_comb for (int i = 0; i < 32; i++) index.Index |= hitWay[i] ? i : 0; TLB_t found; assign found = (hitWay[ 0] ? TLB_entries[ 0] : 78'b0) @@ -40,21 +36,10 @@ module TLB_Lookup ( | (hitWay[ 7] ? TLB_entries[ 7] : 78'b0); logic parity; - // assign parity = |{ - // VPN[12] & found.PageMask[10], - // VPN[10] & ~found.PageMask[10] & found.PageMask[ 8], - // VPN[ 8] & ~found.PageMask[ 8] & found.PageMask[ 6], - // VPN[ 6] & ~found.PageMask[ 6] & found.PageMask[ 4], - // VPN[ 4] & ~found.PageMask[ 4] & found.PageMask[ 2], - // VPN[ 2] & ~found.PageMask[ 2] & found.PageMask[ 0], - // VPN[ 0] & ~found.PageMask[ 0] - // }; - // assign parity = |{VPN & {7'b0, found.PageMask + 1'b1}}; assign parity = VPN[0]; logic [19:0] PFN; assign {PFN, cached, dirty, valid} = parity ? {found.PFN1, found.C1[0], found.D1, found.V1} : {found.PFN0, found.C0[0], found.D0, found.V0}; - // assign PPN = (VPN & {8'b0, found.PageMask}) | (PFN & ~{8'b0, found.PageMask}); assign PPN = PFN; endmodule diff --git a/src/MU/interface.sv b/src/MU/interface.sv index 4e3550f..404ea04 100644 --- a/src/MU/interface.sv +++ b/src/MU/interface.sv @@ -130,12 +130,10 @@ interface CP0_i; logic cpu_tlbr; Random_t cp0_Random; // TLBWR EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID) - // PageMask_t cp0_PageMask; // TLBWI EntryLo_t cp0_EntryLo1; // TLBWI EntryLo_t cp0_EntryLo0; // TLBWI Index_t cp0_Index; // TLBWI + TLBR EntryHi_t tlb_EntryHi; - // PageMask_t tlb_PageMask; EntryLo_t tlb_EntryLo1; EntryLo_t tlb_EntryLo0; Index_t tlb_Index; // TLBP @@ -156,11 +154,9 @@ interface CP0_i; input cp0_Random, input cp0_Index, input cp0_EntryHi, - // input cp0_PageMask, input cp0_EntryLo1, input cp0_EntryLo0, output tlb_EntryHi, - // output tlb_PageMask, output tlb_EntryLo1, output tlb_EntryLo0, output tlb_Index, diff --git a/src/include/TLB.svh b/src/include/TLB.svh index e54dc45..ff40297 100644 --- a/src/include/TLB.svh +++ b/src/include/TLB.svh @@ -7,12 +7,6 @@ typedef struct packed { logic [ 7:0] ASID; } EntryHi_t; -// typedef struct packed { -// logic [ 6:0] zero1; -// logic [11:0] Mask; -// logic [12:0] zero2; -// } PageMask_t; - typedef struct packed { logic [ 5:0] zero; logic [19:0] PFN; @@ -41,7 +35,6 @@ typedef struct packed { typedef struct packed { logic [18:0] VPN2; logic [ 7:0] ASID; - // logic [11:0] PageMask; logic G; logic [19:0] PFN0; logic [ 2:0] C0; diff --git a/src/include/defines.svh b/src/include/defines.svh index fec77a4..c8032af 100644 --- a/src/include/defines.svh +++ b/src/include/defines.svh @@ -2,6 +2,7 @@ `define DEFINES_SVH `define XLEN 32 +`define ENABLE_TLB `define PCRST 32'hBFC00000 `define Off_TRef 9'h000