X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=TLB%2Fsrc%2Fariane%2Fmmu.py;h=0cc04dbb6756d608b86313da72f698cb29fc36f9;hb=23e6065ac7e32e20f92553b810fb30baca2eb2d9;hp=d85abc9f2bd25d336a942c0fcdc63cb2575bc8dd;hpb=8328b357c1b5196373befc4363181353d23e53e9;p=soc.git diff --git a/TLB/src/ariane/mmu.py b/TLB/src/ariane/mmu.py index d85abc9f..0cc04dbb 100644 --- a/TLB/src/ariane/mmu.py +++ b/TLB/src/ariane/mmu.py @@ -19,7 +19,9 @@ import ariane_pkg::*; """ from nmigen import Const, Signal, Cat, Module -from ptw import DCacheReqI, DCacheReqO +from ptw import DCacheReqI, DCacheReqO, TLBUpdate, PTE, PTW +from tlb import TLB + PRIV_LVL_M = Const(0b11, 2) PRIV_LVL_S = Const(0b01, 2) @@ -114,295 +116,300 @@ class MMU: # PTW memory interface self.req_port_i = DCacheReqO() self.req_port_o = DCacheReqI() -); - - logic iaccess_err; # insufficient priv to access instr page - logic daccess_err; # insufficient priv to access data page - logic ptw_active; # PTW is currently walking a page table - logic walking_instr; # PTW is walking because of an ITLB miss - logic ptw_error; # PTW threw an exception - - logic [38:0] update_vaddr; - tlb_update_t update_ptw_itlb, update_ptw_dtlb; - - logic itlb_lu_access; - riscv::pte_t itlb_content; - logic itlb_is_2M; - logic itlb_is_1G; - logic itlb_lu_hit; - - logic dtlb_lu_access; - riscv::pte_t dtlb_content; - logic dtlb_is_2M; - logic dtlb_is_1G; - logic dtlb_lu_hit; - - - # Assignments - assign itlb_lu_access = icache_areq_i.fetch_req; - assign dtlb_lu_access = lsu_req_i; - - - tlb #( - .TLB_ENTRIES ( INSTR_TLB_ENTRIES ), - .ASID_WIDTH ( ASID_WIDTH ) - ) i_itlb ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( flush_tlb_i ), - - .update_i ( update_ptw_itlb ), - - .lu_access_i ( itlb_lu_access ), - .lu_asid_i ( asid_i ), - .lu_vaddr_i ( icache_areq_i.fetch_vaddr ), - .lu_content_o ( itlb_content ), - - .lu_is_2M_o ( itlb_is_2M ), - .lu_is_1G_o ( itlb_is_1G ), - .lu_hit_o ( itlb_lu_hit ) - ); - - tlb #( - .TLB_ENTRIES ( DATA_TLB_ENTRIES ), - .ASID_WIDTH ( ASID_WIDTH ) - ) i_dtlb ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_i ( flush_tlb_i ), - - .update_i ( update_ptw_dtlb ), - - .lu_access_i ( dtlb_lu_access ), - .lu_asid_i ( asid_i ), - .lu_vaddr_i ( lsu_vaddr_i ), - .lu_content_o ( dtlb_content ), - - .lu_is_2M_o ( dtlb_is_2M ), - .lu_is_1G_o ( dtlb_is_1G ), - .lu_hit_o ( dtlb_lu_hit ) - ); - - - ptw #( - .ASID_WIDTH ( ASID_WIDTH ) - ) i_ptw ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .ptw_active_o ( ptw_active ), - .walking_instr_o ( walking_instr ), - .ptw_error_o ( ptw_error ), - .enable_translation_i ( enable_translation_i ), - - .update_vaddr_o ( update_vaddr ), - .itlb_update_o ( update_ptw_itlb ), - .dtlb_update_o ( update_ptw_dtlb ), - - .itlb_access_i ( itlb_lu_access ), - .itlb_hit_i ( itlb_lu_hit ), - .itlb_vaddr_i ( icache_areq_i.fetch_vaddr ), - - .dtlb_access_i ( dtlb_lu_access ), - .dtlb_hit_i ( dtlb_lu_hit ), - .dtlb_vaddr_i ( lsu_vaddr_i ), - - .req_port_i ( req_port_i ), - .req_port_o ( req_port_o ), - - .* - ); - - # ila_1 i_ila_1 ( - # .clk(clk_i), # input wire clk - # .probe0({req_port_o.address_tag, req_port_o.address_index}), - # .probe1(req_port_o.data_req), # input wire [63:0] probe1 - # .probe2(req_port_i.data_gnt), # input wire [0:0] probe2 - # .probe3(req_port_i.data_rdata), # input wire [0:0] probe3 - # .probe4(req_port_i.data_rvalid), # input wire [0:0] probe4 - # .probe5(ptw_error), # input wire [1:0] probe5 - # .probe6(update_vaddr), # input wire [0:0] probe6 - # .probe7(update_ptw_itlb.valid), # input wire [0:0] probe7 - # .probe8(update_ptw_dtlb.valid), # input wire [0:0] probe8 - # .probe9(dtlb_lu_access), # input wire [0:0] probe9 - # .probe10(lsu_vaddr_i), # input wire [0:0] probe10 - # .probe11(dtlb_lu_hit), # input wire [0:0] probe11 - # .probe12(itlb_lu_access), # input wire [0:0] probe12 - # .probe13(icache_areq_i.fetch_vaddr), # input wire [0:0] probe13 - # .probe14(itlb_lu_hit) # input wire [0:0] probe13 - # ); - - #----------------------- - # Instruction Interface - #----------------------- - # The instruction interface is a simple request response interface - always_comb begin : instr_interface + + def elaborate(self, platform): + iaccess_err = Signal() # insufficient priv to access instr page + daccess_err = Signal() # insufficient priv to access data page + ptw_active = Signal() # PTW is currently walking a page table + walking_instr = Signal() # PTW is walking because of an ITLB miss + ptw_error = Signal() # PTW threw an exception + + update_vaddr = Signal(39) + uaddr64 = Cat(update_vaddr, Const(0, 25)) # extend to 64bit with zeros + update_ptw_itlb = TLBUpdate() + update_ptw_dtlb = TLBUpdate() + + itlb_lu_access = Signal() + itlb_content = PTE() + itlb_is_2M = Signal() + itlb_is_1G = Signal() + itlb_lu_hit = Signal() + + dtlb_lu_access = Signal() + dtlb_content = PTE() + dtlb_is_2M = Signal() + dtlb_is_1G = Signal() + dtlb_lu_hit = Signal() + + # Assignments + m.d.comb += [itlb_lu_access.eq(icache_areq_i.fetch_req), + dtlb_lu_access.eq(lsu_req_i) + ] + + # ITLB + m.submodules.i_tlb = i_tlb = TLB(INSTR_TLB_ENTRIES, ASID_WIDTH) + m.d.comb += [i_tlb.flush_i.eq(flush_tlb_i), + i_tlb.update_i.eq(update_ptw_itlb), + i_tlb.lu_access_i.eq(itlb_lu_access), + i_tlb.lu_asid_i.eq(asid_i), + i_tlb.lu_vaddr_i.eq(icache_areq_i.fetch_vaddr), + itlb_content.eq(i_tlb.lu_content_o), + itlb_is_2M.eq(i_tlb.lu_is_2M_o), + itlb_is_1G.eq(i_tlb.lu_is_1G_o), + itlb_lu_hit.eq(i_tlb.lu_hit_o), + ] + + # DTLB + m.submodules.d_tlb = d_tlb = TLB(DATA_TLB_ENTRIES, ASID_WIDTH) + m.d.comb += [d_tlb.flush_i.eq(flush_tlb_i), + d_tlb.update_i.eq(update_ptw_dtlb), + d_tlb.lu_access_i.eq(dtlb_lu_access), + d_tlb.lu_asid_i.eq(asid_i), + d_tlb.lu_vaddr_i.eq(lsu_vaddr_i), + dtlb_content.eq(d_tlb.lu_content_o), + dtlb_is_2M.eq(d_tlb.lu_is_2M_o), + dtlb_is_1G.eq(d_tlb.lu_is_1G_o), + dtlb_lu_hit.eq(d_tlb.lu_hit_o), + ] + + # PTW + m.submodules.ptw = ptw = PTW(ASID_WIDTH) + m.d.comb += [ptw_active.eq(ptw.ptw_active_o), + walking_instr.eq(ptw.walking_instr_o), + ptw_error.eq(ptw.ptw_error_o), + ptw.enable_translation_i.eq(enable_translation_i), + + update_vaddr.eq(ptw.update_vaddr_o), + update_ptw_itlb.eq(ptw.itlb_update_o), + update_ptw_dtlb.eq(ptw.dtlb_update_o), + + ptw.itlb_access_i.eq(itlb_lu_access), + ptw.itlb_hit_i.eq(itlb_lu_hit), + ptw.itlb_vaddr_i.eq(icache_areq_i.fetch_vaddr), + + ptw.dtlb_access_i.eq(dtlb_lu_access), + ptw.dtlb_hit_i.eq(dtlb_lu_hit), + ptw.dtlb_vaddr_i.eq(lsu_vaddr_i), + + ptw.req_port_i.eq(req_port_i), + req_port_o.eq(ptw.req_port_o), + ] + + # ila_1 i_ila_1 ( + # .clk(clk_i), # input wire clk + # .probe0({req_port_o.address_tag, req_port_o.address_index}), + # .probe1(req_port_o.data_req), # input wire [63:0] probe1 + # .probe2(req_port_i.data_gnt), # input wire [0:0] probe2 + # .probe3(req_port_i.data_rdata), # input wire [0:0] probe3 + # .probe4(req_port_i.data_rvalid), # input wire [0:0] probe4 + # .probe5(ptw_error), # input wire [1:0] probe5 + # .probe6(update_vaddr), # input wire [0:0] probe6 + # .probe7(update_ptw_itlb.valid), # input wire [0:0] probe7 + # .probe8(update_ptw_dtlb.valid), # input wire [0:0] probe8 + # .probe9(dtlb_lu_access), # input wire [0:0] probe9 + # .probe10(lsu_vaddr_i), # input wire [0:0] probe10 + # .probe11(dtlb_lu_hit), # input wire [0:0] probe11 + # .probe12(itlb_lu_access), # input wire [0:0] probe12 + # .probe13(icache_areq_i.fetch_vaddr), # input wire [0:0] probe13 + # .probe14(itlb_lu_hit) # input wire [0:0] probe13 + # ); + + #----------------------- + # Instruction Interface + #----------------------- + # The instruction interface is a simple request response interface + # MMU disabled: just pass through - icache_areq_o.fetch_valid = icache_areq_i.fetch_req; - icache_areq_o.fetch_paddr = icache_areq_i.fetch_vaddr; # play through in case we disabled address translation + m.d.comb += [icache_areq_o.fetch_valid.eq(icache_areq_i.fetch_req), + # play through in case we disabled address translation + icache_areq_o.fetch_paddr.eq(icache_areq_i.fetch_vaddr) + ] # two potential exception sources: # 1. HPTW threw an exception -> signal with a page fault exception - # 2. We got an access error because of insufficient permissions -> throw an access exception - icache_areq_o.fetch_exception = '0; - # Check whether we are allowed to access this memory region from a fetch perspective - iaccess_err = icache_areq_i.fetch_req && (((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u) - || ((priv_lvl_i == riscv::PRIV_LVL_S) && itlb_content.u)); - - # MMU enabled: address from TLB, request delayed until hit. Error when TLB - # hit and no access right or TLB hit and translated address not valid (e.g. - # AXI decode error), or when PTW performs walk due to ITLB miss and raises + # 2. We got an access error because of insufficient permissions -> + # throw an access exception + m.d.comb += icache_areq_o.fetch_exception.eq(0) + # Check whether we are allowed to access this memory region + # from a fetch perspective + m.d.comb += iaccess_err.eq(icache_areq_i.fetch_req & \ + (((priv_lvl_i == PRIV_LVL_U) & \ + ~itlb_content.u) | \ + ((priv_lvl_i == :PRIV_LVL_S) & \ + itlb_content.u))) + + # MMU enabled: address from TLB, request delayed until hit. + # Error when TLB hit and no access right or TLB hit and + # translated address not valid (e.g. AXI decode error), + # or when PTW performs walk due to ITLB miss and raises # an error. - if (enable_translation_i) begin - # we work with SV39, so if VM is enabled, check that all bits [63:38] are equal - if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[63:38]) == 1'b1 || (|icache_areq_i.fetch_vaddr[63:38]) == 1'b0)) begin - icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, icache_areq_i.fetch_vaddr, 1'b1}; - end - - icache_areq_o.fetch_valid = 1'b0; + with m.If (self.enable_translation_i): + # we work with SV39, so if VM is enabled, check that + # all bits [63:38] are equal + with m.If (icache_areq_i.fetch_req & \ + ~(((~icache_areq_i.fetch_vaddr[38:64]) == 0) | \ + (icache_areq_i.fetch_vaddr[38:64]) == 0)): + fe = icache_areq_o.fetch_exception + m.d.comb += [fe.cause.eq(INSTR_ACCESS_FAULT), + fe.tval.eq(icache_areq_i.fetch_vaddr), + fe.valid.eq(1) + ] + + m.d.comb += icache_areq_o.fetch_valid.eq(0) # 4K page - icache_areq_o.fetch_paddr = {itlb_content.ppn, icache_areq_i.fetch_vaddr[11:0]}; + paddr = Signal.like(icache_areq_o.fetch_paddr) + paddr4k = Cat(icache_areq_i.fetch_vaddr[0:12], itlb_content.ppn) + m.d.comb += paddr.eq(paddr4k) # Mega page - if (itlb_is_2M) begin - icache_areq_o.fetch_paddr[20:12] = icache_areq_i.fetch_vaddr[20:12]; + with m.If(itlb_is_2M): + m.d.comb += paddr[12:21].eq(icache_areq_i.fetch_vaddr[12:21]) end # Giga page - if (itlb_is_1G) begin - icache_areq_o.fetch_paddr[29:12] = icache_areq_i.fetch_vaddr[29:12]; - end + with m.If(itlb_is_1G): + m.d.comb += paddr[12:30].eq(icache_areq_i.fetch_vaddr[12:30]) + m.d.comb += icache_areq_o.fetch_paddr.eq(paddr) # --------- # ITLB Hit # -------- # if we hit the ITLB output the request signal immediately - if (itlb_lu_hit) begin - icache_areq_o.fetch_valid = icache_areq_i.fetch_req; + with m.If(itlb_lu_hit): + m.d.comb += icache_areq_o.fetch_valid.eq( + icache_areq_i.fetch_req) # we got an access error - if (iaccess_err) begin + with m.If (iaccess_err): # throw a page fault - icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, icache_areq_i.fetch_vaddr, 1'b1}; - end - end else + fe = icache_areq_o.fetch_exception + m.d.comb += [fe.cause.eq(INSTR_ACCESS_FAULT), + fe.tval.eq(icache_areq_i.fetch_vaddr), + fe.valid.eq(1) + ] # --------- # ITLB Miss # --------- # watch out for exceptions happening during walking the page table - if (ptw_active && walking_instr) begin - icache_areq_o.fetch_valid = ptw_error; - icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; - end - end - end - - #----------------------- - # Data Interface - #----------------------- - logic [63:0] lsu_vaddr_n, lsu_vaddr_q; - riscv::pte_t dtlb_pte_n, dtlb_pte_q; - exception_t misaligned_ex_n, misaligned_ex_q; - logic lsu_req_n, lsu_req_q; - logic lsu_is_store_n, lsu_is_store_q; - logic dtlb_hit_n, dtlb_hit_q; - logic dtlb_is_2M_n, dtlb_is_2M_q; - logic dtlb_is_1G_n, dtlb_is_1G_q; - - # check if we need to do translation or if we are always ready (e.g.: we are not translating anything) - assign lsu_dtlb_hit_o = (en_ld_st_translation_i) ? dtlb_lu_hit : 1'b1; - - # The data interface is simpler and only consists of a request/response interface - always_comb begin : data_interface - # save request and DTLB response - lsu_vaddr_n = lsu_vaddr_i; - lsu_req_n = lsu_req_i; - misaligned_ex_n = misaligned_ex_i; - dtlb_pte_n = dtlb_content; - dtlb_hit_n = dtlb_lu_hit; - lsu_is_store_n = lsu_is_store_i; - dtlb_is_2M_n = dtlb_is_2M; - dtlb_is_1G_n = dtlb_is_1G; - - lsu_paddr_o = lsu_vaddr_q; - lsu_valid_o = lsu_req_q; - lsu_exception_o = misaligned_ex_q; - # mute misaligned exceptions if there is no request otherwise they will throw accidental exceptions - misaligned_ex_n.valid = misaligned_ex_i.valid & lsu_req_i; - - # Check if the User flag is set, then we may only access it in supervisor mode - # if SUM is enabled - daccess_err = (ld_st_priv_lvl_i == riscv::PRIV_LVL_S && !sum_i && dtlb_pte_q.u) || # SUM is not set and we are trying to access a user page in supervisor mode - (ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u); # this is not a user page but we are in user mode and trying to access it - # translation is enabled and no misaligned exception occurred - if (en_ld_st_translation_i && !misaligned_ex_q.valid) begin - lsu_valid_o = 1'b0; - # 4K page - lsu_paddr_o = {dtlb_pte_q.ppn, lsu_vaddr_q[11:0]}; - # Mega page - if (dtlb_is_2M_q) begin - lsu_paddr_o[20:12] = lsu_vaddr_q[20:12]; - end - # Giga page - if (dtlb_is_1G_q) begin - lsu_paddr_o[29:12] = lsu_vaddr_q[29:12]; - end - # --------- - # DTLB Hit - # -------- - if (dtlb_hit_q && lsu_req_q) begin - lsu_valid_o = 1'b1; - # this is a store - if (lsu_is_store_q) begin - # check if the page is write-able and we are not violating privileges - # also check if the dirty flag is set - if (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d) begin - lsu_exception_o = {riscv::STORE_PAGE_FAULT, lsu_vaddr_q, 1'b1}; - end - - # this is a load, check for sufficient access privileges - throw a page fault if necessary - end else if (daccess_err) begin - lsu_exception_o = {riscv::LOAD_PAGE_FAULT, lsu_vaddr_q, 1'b1}; + with m.Elif(ptw_active & walking_instr): + m.d.comb += icache_areq_o.fetch_valid.eq(ptw_error) + fe = icache_areq_o.fetch_exception + m.d.comb += [fe.cause.eq(INSTR_PAGE_FAULT), + fe.tval.eq(uaddr64), + fe.valid.eq(1) + ] + + #----------------------- + # Data Interface + #----------------------- + + lsu_vaddr = Signal(64) + dtlb_pte = PTE() + misaligned_ex = RVException() + lsu_req = Signal() + lsu_is_store = Signal() + dtlb_hit = Signal() + dtlb_is_2M = Signal() + dtlb_is_1G = Signal() + + # check if we need to do translation or if we are always + # ready (e.g.: we are not translating anything) + m.d.comb += lsu_dtlb_hit_o.eq(Mux(en_ld_st_translation_i), + dtlb_lu_hit, 1) + + # The data interface is simpler and only consists of a + # request/response interface + m.d.comb += [ + # save request and DTLB response + lsu_vaddr.eq(lsu_vaddr_i), + lsu_req.eq(lsu_req_i), + misaligned_ex.eq(misaligned_ex_i), + dtlb_pte.eq(dtlb_content), + dtlb_hit.eq(dtlb_lu_hit), + lsu_is_store.eq(lsu_is_store_i), + dtlb_is_2M.eq(dtlb_is_2M), + dtlb_is_1G.eq(dtlb_is_1G), + ] + m.d.sync += [ + lsu_paddr_o.eq(lsu_vaddr), + lsu_valid_o.eq(lsu_req), + lsu_exception_o.eq(misaligned_ex), + ] + + m.d.comb += [ + # mute misaligned exceptions if there is no request + # otherwise they will throw accidental exceptions + misaligned_ex_n.valid.eq(misaligned_ex_i.valid & lsu_req_i), + + # Check if the User flag is set, then we may only + # access it in supervisor mode if SUM is enabled + + daccess_err.eq( + # SUM is not set and we are trying to access a user + # page in supervisor mode + ld_st_priv_lvl_i == PRIV_LVL_S & ~sum_i & \ + dtlb_pte_q.u) | \ + # this is not a user page but we are in user mode and + # trying to access it + (ld_st_priv_lvl_i == PRIV_LVL_U & ~dtlb_pte_q.u)) + + # translation is enabled and no misaligned exception occurred + with m.If(en_ld_st_translation_i & ~misaligned_ex_q.valid): + m.d.comb += lsu_valid_o.eq(0) + # 4K page + paddr = Signal.like(lsu_vaddr_q) + paddr4k = Cat(lsu_vaddr_q[0:12], itlb_content.ppn) + m.d.comb += paddr.eq(paddr4k) + # Mega page + with m.If(dtlb_is_2M): + m.d.comb += paddr[12:21].eq(lsu_vaddr_q[12:21]) end - end else + # Giga page + with m.If(dtlb_is_1G): + m.d.comb += paddr[12:30].eq(lsu_vaddr_q[12:30]) + m.d.comb += lsu_paddr_o.eq(paddr) + + # --------- + # DTLB Hit + # -------- + with m.If(dtlb_hit_q & lsu_req_q): + m.d.comb += lsu_valid_o.eq(1) + # this is a store + with m.If (lsu_is_store_q): + # check if the page is write-able and + # we are not violating privileges + # also check if the dirty flag is set + with m.If(~dtlb_pte_q.w | daccess_err | ~dtlb_pte_q.d): + le = lsu_exception_o + m.d.comb += [le.cause.eq(STORE_PAGE_FAULT), + le.tval.eq(lsu_vaddr_q), + le.valid.eq(1) + ] + + # this is a load, check for sufficient access + # privileges - throw a page fault if necessary + with m.Elif(daccess_err): + le = lsu_exception_o + m.d.comb += [le.cause.eq(LOAD_PAGE_FAULT), + le.tval.eq(lsu_vaddr_q), + le.valid.eq(1) + ] + # --------- + # DTLB Miss + # --------- + # watch out for exceptions + with m.Elif (ptw_active & ~walking_instr): + # page table walker threw an exception + with m.If (ptw_error): + # an error makes the translation valid + m.d.comb += lsu_valid_o.eq(1) + # the page table walker can only throw page faults + with m.If (lsu_is_store_q): + le = lsu_exception_o + m.d.comb += [le.cause.eq(STORE_PAGE_FAULT), + le.tval.eq(uaddr64), + le.valid.eq(1) + ] + with m.Else(): + m.d.comb += [le.cause.eq(LOAD_PAGE_FAULT), + le.tval.eq(uaddr64), + le.valid.eq(1) + ] - # --------- - # DTLB Miss - # --------- - # watch out for exceptions - if (ptw_active && !walking_instr) begin - # page table walker threw an exception - if (ptw_error) begin - # an error makes the translation valid - lsu_valid_o = 1'b1; - # the page table walker can only throw page faults - if (lsu_is_store_q) begin - lsu_exception_o = {riscv::STORE_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; - end else begin - lsu_exception_o = {riscv::LOAD_PAGE_FAULT, {25'b0, update_vaddr}, 1'b1}; - end - end - end - end - end - # ---------- - # Registers - # ---------- - always_ff @(posedge clk_i or negedge rst_ni) begin - if (~rst_ni) begin - lsu_vaddr_q <= '0; - lsu_req_q <= '0; - misaligned_ex_q <= '0; - dtlb_pte_q <= '0; - dtlb_hit_q <= '0; - lsu_is_store_q <= '0; - dtlb_is_2M_q <= '0; - dtlb_is_1G_q <= '0; - end else begin - lsu_vaddr_q <= lsu_vaddr_n; - lsu_req_q <= lsu_req_n; - misaligned_ex_q <= misaligned_ex_n; - dtlb_pte_q <= dtlb_pte_n; - dtlb_hit_q <= dtlb_hit_n; - lsu_is_store_q <= lsu_is_store_n; - dtlb_is_2M_q <= dtlb_is_2M_n; - dtlb_is_1G_q <= dtlb_is_1G_n; - end - end -endmodule