From 157f43245c677481ccf9d591331658858bbf5057 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 14 Apr 2019 12:57:49 +0100 Subject: [PATCH] correct python syntax errors --- TLB/src/ariane/ptw.py | 268 ++++++++++++++++++++++-------------------- TLB/src/ariane/tlb.py | 139 +++++++++++----------- 2 files changed, 209 insertions(+), 198 deletions(-) diff --git a/TLB/src/ariane/ptw.py b/TLB/src/ariane/ptw.py index 793be33f..9f7c0ad0 100644 --- a/TLB/src/ariane/ptw.py +++ b/TLB/src/ariane/ptw.py @@ -18,6 +18,14 @@ import ariane_pkg::*; """ +from nmigen import Const, Signal +from math import log + +DCACHE_SET_ASSOC = 8 +CONFIG_L1D_SIZE = 32*1024 +DCACHE_INDEX_WIDTH = int(log(CONFIG_L1D_SIZE / DCACHE_SET_ASSOC)) +DCACHE_TAG_WIDTH = 56 - DCACHE_INDEX_WIDTH + class DCacheReqI: def __init__(self): self.address_index = Signal(DCACHE_INDEX_WIDTH) @@ -39,7 +47,7 @@ class DCacheReqO: ASID_WIDTH = 1 -class PTE(RecordObject): +class PTE: #(RecordObject): def __init__(self): self.reserved = Signal(10) self.ppn = Signal(44) @@ -70,126 +78,126 @@ LVL3 = Const(2, 2) class PTW: - flush_i = Signal() # flush everything, we need to do this because - # actually everything we do is speculative at this stage - # e.g.: there could be a CSR instruction that changes everything - ptw_active_o = Signal() - walking_instr_o = Signal() # set when walking for TLB - ptw_error_o = Signal() # set when an error occurred - enable_translation_i = Signal() # CSRs indicate to enable SV39 - en_ld_st_translation_i = Signal() # enable VM translation for load/stores - - lsu_is_store_i = Signal() , # this translation triggered by a store - # PTW memory interface - req_port_i = DCacheReqO() - req_port_o = DCacheReqI() - - # to TLBs, update logic - itlb_update_o = TLBUpdate() - dtlb_update_o = TLBUpdate() - - update_vaddr_o = Signal(39) - - asid_i = Signal(ASID_WIDTH) - # from TLBs - # did we miss? - itlb_access_i = Signal() - itlb_hit_i = Signal() - itlb_vaddr_i = Signal(64) - - dtlb_access_i = Signal() - dtlb_hit_i = Signal() - dtlb_vaddr_i = Signal(64) - # from CSR file - satp_ppn_i = Signal(44) # ppn from satp - mxr_i = Signal() - # Performance counters - itlb_miss_o = Signal() - dtlb_miss_o = Signal() - -); - - # input registers - data_rvalid = Signal() - data_rdata = Signal(64) - - pte = PTE() - assign pte = riscv::pte_t(data_rdata); - - ptw_lvl = Signal(2, reset=LVL1) - - # is this an instruction page table walk? - is_instr_ptw = Signal() - global_mapping = Signal() - # latched tag signal - tag_valid = Signal() - # register the ASID - tlb_update_asid = Signal(ASID_WIDTH) - # register the VPN we need to walk, SV39 defines a 39 bit virtual address - vaddr = Signal(64) - # 4 byte aligned physical pointer - ptw_pptr = Signal(56) - - end = DCACHE_INDEX_WIDTH + DCACHE_TAG_WIDTH - m.d.sync += [ - # Assignments - update_vaddr_o.eq(vaddr), - - ptw_active_o.eq(state != IDLE), - walking_instr_o.eq(is_instr_ptw), - # directly output the correct physical address - req_port_o.address_index.eq(ptw_pptr[0:DCACHE_INDEX_WIDTH]), - req_port_o.address_tag.eq(ptw_pptr[DCACHE_INDEX_WIDTH:end]), - # we are never going to kill this request - req_port_o.kill_req.eq(0), - # we are never going to write with the HPTW - req_port_o.data_wdata.eq(Const(0, 64)), - # ----------- - # TLB Update - # ----------- - itlb_update_o.vpn.eq(vaddr[12:39]), - dtlb_update_o.vpn.eq(vaddr[12:39]), - # update the correct page table level - itlb_update_o.is_2M.eq(ptw_lvl == LVL2), - itlb_update_o.is_1G.eq(ptw_lvl == LVL1), - dtlb_update_o.is_2M.eq(ptw_lvl == LVL2), - dtlb_update_o.is_1G.eq(ptw_lvl == LVL1), - # output the correct ASID - itlb_update_o.asid.eq(tlb_update_asid), - dtlb_update_o.asid.eq(tlb_update_asid), - # set the global mapping bit - itlb_update_o.content.eq(pte | (global_mapping << 5)), - dtlb_update_o.content.eq(pte | (global_mapping << 5)), - - ] - m.d.comb += [ - req_port_o.tag_valid.eq(tag_valid), - ] - #------------------- - # Page table walker - #------------------- - # A virtual address va is translated into a physical address pa as follows: - # 1. Let a be sptbr.ppn × PAGESIZE, and let i = LEVELS-1. (For Sv39, - # PAGESIZE=2^12 and LEVELS=3.) - # 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For - # Sv32, PTESIZE=4.) - # 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, stop and raise an access - # exception. - # 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5. - # Otherwise, this PTE is a pointer to the next level of the page table. - # Let i=i-1. If i < 0, stop and raise an access exception. Otherwise, let - # a = pte.ppn × PAGESIZE and go to step 2. - # 5. A leaf PTE has been found. Determine if the requested memory access - # is allowed by the pte.r, pte.w, and pte.x bits. If not, stop and - # raise an access exception. Otherwise, the translation is successful. - # Set pte.a to 1, and, if the memory access is a store, set pte.d to 1. - # The translated physical address is given as follows: - # - pa.pgoff = va.pgoff. - # - If i > 0, then this is a superpage translation and - # pa.ppn[i-1:0] = va.vpn[i-1:0]. - # - pa.ppn[LEVELS-1:i] = pte.ppn[LEVELS-1:i]. - # 6. If i > 0 and pa.ppn[i − 1 : 0] != 0, this is a misaligned superpage; - # stop and raise a page-fault exception. + def __init__(self): + flush_i = Signal() # flush everything, we need to do this because + # actually everything we do is speculative at this stage + # e.g.: there could be a CSR instruction that changes everything + ptw_active_o = Signal() + walking_instr_o = Signal() # set when walking for TLB + ptw_error_o = Signal() # set when an error occurred + enable_translation_i = Signal() # CSRs indicate to enable SV39 + en_ld_st_translation_i = Signal() # enable VM translation for ld/st + + lsu_is_store_i = Signal() , # this translation triggered by store + # PTW memory interface + req_port_i = DCacheReqO() + req_port_o = DCacheReqI() + + # to TLBs, update logic + itlb_update_o = TLBUpdate() + dtlb_update_o = TLBUpdate() + + update_vaddr_o = Signal(39) + + asid_i = Signal(ASID_WIDTH) + # from TLBs + # did we miss? + itlb_access_i = Signal() + itlb_hit_i = Signal() + itlb_vaddr_i = Signal(64) + + dtlb_access_i = Signal() + dtlb_hit_i = Signal() + dtlb_vaddr_i = Signal(64) + # from CSR file + satp_ppn_i = Signal(44) # ppn from satp + mxr_i = Signal() + # Performance counters + itlb_miss_o = Signal() + dtlb_miss_o = Signal() + + + # input registers + data_rvalid = Signal() + data_rdata = Signal(64) + + pte = PTE() + m.d.comb += pte.eq(data_rdata) + + ptw_lvl = Signal(2, reset=LVL1) + + # is this an instruction page table walk? + is_instr_ptw = Signal() + global_mapping = Signal() + # latched tag signal + tag_valid = Signal() + # register the ASID + tlb_update_asid = Signal(ASID_WIDTH) + # register the VPN we need to walk, SV39 defines a 39 bit virtual address + vaddr = Signal(64) + # 4 byte aligned physical pointer + ptw_pptr = Signal(56) + + end = DCACHE_INDEX_WIDTH + DCACHE_TAG_WIDTH + m.d.sync += [ + # Assignments + update_vaddr_o.eq(vaddr), + + ptw_active_o.eq(state != IDLE), + walking_instr_o.eq(is_instr_ptw), + # directly output the correct physical address + req_port_o.address_index.eq(ptw_pptr[0:DCACHE_INDEX_WIDTH]), + req_port_o.address_tag.eq(ptw_pptr[DCACHE_INDEX_WIDTH:end]), + # we are never going to kill this request + req_port_o.kill_req.eq(0), + # we are never going to write with the HPTW + req_port_o.data_wdata.eq(Const(0, 64)), + # ----------- + # TLB Update + # ----------- + itlb_update_o.vpn.eq(vaddr[12:39]), + dtlb_update_o.vpn.eq(vaddr[12:39]), + # update the correct page table level + itlb_update_o.is_2M.eq(ptw_lvl == LVL2), + itlb_update_o.is_1G.eq(ptw_lvl == LVL1), + dtlb_update_o.is_2M.eq(ptw_lvl == LVL2), + dtlb_update_o.is_1G.eq(ptw_lvl == LVL1), + # output the correct ASID + itlb_update_o.asid.eq(tlb_update_asid), + dtlb_update_o.asid.eq(tlb_update_asid), + # set the global mapping bit + itlb_update_o.content.eq(pte | (global_mapping << 5)), + dtlb_update_o.content.eq(pte | (global_mapping << 5)), + + ] + m.d.comb += [ + req_port_o.tag_valid.eq(tag_valid), + ] + #------------------- + # Page table walker + #------------------- + # A virtual address va is translated into a physical address pa as follows: + # 1. Let a be sptbr.ppn × PAGESIZE, and let i = LEVELS-1. (For Sv39, + # PAGESIZE=2^12 and LEVELS=3.) + # 2. Let pte be the value of the PTE at address a+va.vpn[i]×PTESIZE. (For + # Sv32, PTESIZE=4.) + # 3. If pte.v = 0, or if pte.r = 0 and pte.w = 1, stop and raise an access + # exception. + # 4. Otherwise, the PTE is valid. If pte.r = 1 or pte.x = 1, go to step 5. + # Otherwise, this PTE is a pointer to the next level of the page table. + # Let i=i-1. If i < 0, stop and raise an access exception. Otherwise, let + # a = pte.ppn × PAGESIZE and go to step 2. + # 5. A leaf PTE has been found. Determine if the requested memory access + # is allowed by the pte.r, pte.w, and pte.x bits. If not, stop and + # raise an access exception. Otherwise, the translation is successful. + # Set pte.a to 1, and, if the memory access is a store, set pte.d to 1. + # The translated physical address is given as follows: + # - pa.pgoff = va.pgoff. + # - If i > 0, then this is a superpage translation and + # pa.ppn[i-1:0] = va.vpn[i-1:0]. + # - pa.ppn[LEVELS-1:i] = pte.ppn[LEVELS-1:i]. + # 6. If i > 0 and pa.ppn[i − 1 : 0] != 0, this is a misaligned superpage; + # stop and raise a page-fault exception. m.d.sync += tag_valid.eq(0) @@ -197,11 +205,11 @@ class PTW: m.d.comb += [ # PTW memory interface req_port_o.data_req.eq(0), - req_port_o.data_be.eq(Const(0xFF, 8)) - req_port_o.data_size.eq(Const(0bb11, 2)) + req_port_o.data_be.eq(Const(0xFF, 8)), + req_port_o.data_size.eq(Const(0b11, 2)), req_port_o.data_we.eq(0), ptw_error_o.eq(0), - itlb_update_o.valid.eq(0) + itlb_update_o.valid.eq(0), dtlb_update_o.valid.eq(0), itlb_miss_o.eq(0), @@ -220,10 +228,10 @@ class PTW: with m.If(enable_translation_i & itlb_access_i & \ ~itlb_hit_i & ~dtlb_access_i): pptr = Cat(Const(0, 3), itlb_vaddr_i[30:39], satp_ppn_i) - m.d.sync += [ptw_pptr.eq(pptr) + m.d.sync += [ptw_pptr.eq(pptr), is_instr_ptw.eq(1), vaddr.eq(itlb_vaddr_i), - tlb_update_asid.eq(asid_i). + tlb_update_asid.eq(asid_i), ] m.d.comb += [itlb_miss_o.eq(1)] m.next = "WAIT_GRANT" @@ -231,9 +239,9 @@ class PTW: with m.Elif(en_ld_st_translation_i & dtlb_access_i & \ ~dtlb_hit_i): pptr = Cat(Const(0, 3), dtlb_vaddr_i[30:39], satp_ppn_i) - m.d.sync += [ptw_pptr.eq(pptr) + m.d.sync += [ptw_pptr.eq(pptr), vaddr.eq(dtlb_vaddr_i), - tlb_update_asid.eq(asid_i). + tlb_update_asid.eq(asid_i), ] m.d.comb += [ dtlb_miss_o.eq(1)] m.next = "WAIT_GRANT" @@ -260,7 +268,7 @@ class PTW: # ------------- # If pte.v = 0, or if pte.r = 0 and pte.w = 1, # stop and raise a page-fault exception. - with m.If (~pte.v | (~pte.r & pte.w)) + with m.If (~pte.v | (~pte.r & pte.w)): m.next = "PROPAGATE_ERROR" # ----------- # Valid PTE @@ -357,7 +365,7 @@ class PTW: # wait for the rvalid before going back to IDLE with m.State("WAIT_RVALID"): - m.If (data_rvalid): + with m.If(data_rvalid): m.next = "IDLE" # ------- diff --git a/TLB/src/ariane/tlb.py b/TLB/src/ariane/tlb.py index e9f28c99..b6a5a633 100644 --- a/TLB/src/ariane/tlb.py +++ b/TLB/src/ariane/tlb.py @@ -31,40 +31,42 @@ class TLBEntry: TLB_ENTRIES = 4 ASID_WIDTH = 1 -from .tlb import TLBUpdate, PTE - -module tlb #( - )( - flush_i = Signal(), # Flush signal - # Update TLB - update_i = TLBUpdate() - # Lookup signals - lu_access_i = Signal() - lu_asid_i = Signal(ASID_WIDTH) - lu_vaddr_i = Signal(64) - lu_content_o = PTE() - lu_is_2M_o = Signal() - lu_is_1G_o = Signal() - lu_hit_o = Signal() -) - - tags = TLBEntry() - # SV39 defines three levels of page tables - - content = Array([TLB() for i in range(TLB_ENTRIES)]) - - vpn2 = Signal(9) - vpn1 = Signal(9) - vpn0 = Signal(9) - lu_hit = Signal(TLB_ENTRIES) # to replacement logic - replace_en = Signal(TLB_ENTRIES) # replace the following entry, - # set by replacement strategy - #------------- - # Translation - #------------- - m.d.comb += [ vpn0.eq(lu_vaddr_i[12:21], - vpn1.eq(lu_vaddr_i[21:30], - vpn2.eq(lu_vaddr_i[30:39] +from ptw import TLBUpdate, PTE + +class TLB: + def __init__(self): + self.flush_i = Signal() # Flush signal + # Update TLB + self.update_i = TLBUpdate() + # Lookup signals + self.lu_access_i = Signal() + self.lu_asid_i = Signal(ASID_WIDTH) + self.lu_vaddr_i = Signal(64) + self.lu_content_o = PTE() + self.lu_is_2M_o = Signal() + self.lu_is_1G_o = Signal() + self.lu_hit_o = Signal() + + def elaborate(self, platform): + m = Module() + + tags = TLBEntry() + # SV39 defines three levels of page tables + + content = Array([TLB() for i in range(TLB_ENTRIES)]) + + vpn2 = Signal(9) + vpn1 = Signal(9) + vpn0 = Signal(9) + lu_hit = Signal(TLB_ENTRIES) # to replacement logic + replace_en = Signal(TLB_ENTRIES) # replace the following entry, + # set by replacement strategy + #------------- + # Translation + #------------- + m.d.comb += [ vpn0.eq(lu_vaddr_i[12:21]), + vpn1.eq(lu_vaddr_i[21:30]), + vpn2.eq(lu_vaddr_i[30:39]), ] for i in range(TLB_ENTRIES): @@ -92,15 +94,15 @@ module tlb #( lu_hit[i].eq(1), ] - # ------------------ - # Update and Flush - # ------------------ + # ------------------ + # Update and Flush + # ------------------ for i in range(TLB_ENTRIES): with m.If (flush_i): - # invalidate logic: flush conditions - with m.If ((lu_asid_i == Const(0, ASID_WIDTH) | # all if zero - (lu_asid_i == tags[i].asid): # just this ASID + # invalidate (flush) conditions: all if zero or just this ASID + with m.If (lu_asid_i == Const(0, ASID_WIDTH) | + (lu_asid_i == tags[i].asid)): m.d.sync += tags[i].valid.eq(0) # normal replacement @@ -117,9 +119,10 @@ module tlb #( content[i].eq(update_i.content) ] - # ----------------------------------------------- - # PLRU - Pseudo Least Recently Used Replacement - # ----------------------------------------------- + # ----------------------------------------------- + # PLRU - Pseudo Least Recently Used Replacement + # ----------------------------------------------- + TLBSZ = 2*(TLB_ENTRIES-1) plru_tree = Signal(TLBSZ) @@ -155,7 +158,7 @@ module tlb #( idx_base = (1< MSB, lvl1 <=> MSB-1, ... shift = LOG_TLB - lvl; - new_idx = Const(~((i >> (shift-1)) & 1) + new_idx = Const(~((i >> (shift-1)) & 1)) m.d.sync += plru_tree[idx_base + (i >> shift)].eq(new_idx) # Decode tree to write enable signals @@ -189,28 +192,28 @@ module tlb #( # plur0 & plru1 & plur2 == ~(~plru0 | ~plru1 | ~plru2) m.d.sync += replace_en[i].eq(~Cat(*en).bool()) - #-------------- - # Sanity checks - #-------------- - - assert (TLB_ENTRIES % 2 == 0) and (TLB_ENTRIES > 1)), \ - "TLB size must be a multiple of 2 and greater than 1" - assert (ASID_WIDTH >= 1), - "ASID width must be at least 1") - - """ - # Just for checking - function int countSetBits(logic[TLB_ENTRIES-1:0] vector); - automatic int count = 0; - foreach (vector[idx]) begin - count += vector[idx]; - end - return count; - endfunction - - assert property (@(posedge clk_i)(countSetBits(lu_hit) <= 1)) - else begin $error("More then one hit in TLB!"); $stop(); end - assert property (@(posedge clk_i)(countSetBits(replace_en) <= 1)) - else begin $error("More then one TLB entry selected for next replace!"); - """ + #-------------- + # Sanity checks + #-------------- + + assert (TLB_ENTRIES % 2 == 0) and (TLB_ENTRIES > 1), \ + "TLB size must be a multiple of 2 and greater than 1" + assert (ASID_WIDTH >= 1), \ + "ASID width must be at least 1" + + """ + # Just for checking + function int countSetBits(logic[TLB_ENTRIES-1:0] vector); + automatic int count = 0; + foreach (vector[idx]) begin + count += vector[idx]; + end + return count; + endfunction + + assert property (@(posedge clk_i)(countSetBits(lu_hit) <= 1)) + else $error("More then one hit in TLB!"); $stop(); end + assert property (@(posedge clk_i)(countSetBits(replace_en) <= 1)) + else $error("More then one TLB entry selected for next replace!"); + """ -- 2.30.2