feat: MU rewrite 2

TLB Support
This commit is contained in:
Paul Pan 2022-07-27 18:11:54 +08:00
parent 9ce588757d
commit 4f7fe2adf2
8 changed files with 137 additions and 89 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
`define DEFINES_SVH
`define XLEN 32
`define ENABLE_TLB
`define PCRST 32'hBFC00000
`define Off_TRef 9'h000