From 74cef77cffa704639ba9cb6ec96e6686282e5d2a Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 14 Apr 2019 13:18:16 +0100 Subject: [PATCH] work towards getting PTW translation working --- TLB/src/ariane/ptw.py | 37 ++++++++++++++++++---- TLB/src/ariane/tlb.py | 73 ++++++++++++++++++++++++++----------------- 2 files changed, 76 insertions(+), 34 deletions(-) diff --git a/TLB/src/ariane/ptw.py b/TLB/src/ariane/ptw.py index 9f7c0ad0..220c3bda 100644 --- a/TLB/src/ariane/ptw.py +++ b/TLB/src/ariane/ptw.py @@ -61,15 +61,30 @@ class PTE: #(RecordObject): self.r = Signal() self.v = Signal() + def eq(self, x): + return [self.reserved.eq(x.reserved), + self.ppn.eq(x.ppn), self.rsw.eq(x.rsw), + self.d.eq(x.d), self.a.eq(x.a), self.g.eq(x.g), + self.u.eq(x.u), self.x.eq(x.x), self.w.eq(x.w), + self.r.eq(x.r), self.v.eq(x.v)] + + def ports(self): + return [self.reserved, self.ppn, self.rsw, self.d, self.a, self.g, + self.u, self.x, self.w, self.r, self.v] + class TLBUpdate: def __init__(self): - valid = Signal() # valid flag - is_2M = Signal() - is_1G = Signal() - vpn = Signal(27) - asid = Signal(ASID_WIDTH) - content = PTE() + self.valid = Signal() # valid flag + self.is_2M = Signal() + self.is_1G = Signal() + self.vpn = Signal(27) + self.asid = Signal(ASID_WIDTH) + self.content = PTE() + + def ports(self): + return [self.valid, self.is_2M, self.is_1G, self.vpn, self.asid, + self.content.ports()] # SV39 defines three levels of page tables LVL1 = Const(0, 2) @@ -389,3 +404,13 @@ class PTW: data_rvalid.eq(req_port_i.data_rvalid) ] +""" +if __name__ == '__main__': + dut = PTE() + ports = [dut.p.i_valid, dut.n.i_ready, + dut.n.o_valid, dut.p.o_ready] + \ + [dut.p.i_data] + [dut.n.o_data] + vl = rtlil.convert(dut, ports=ports) + with open("test_bufunbuf999.il", "w") as f: + f.write(vl) +""" diff --git a/TLB/src/ariane/tlb.py b/TLB/src/ariane/tlb.py index b6a5a633..dce553d6 100644 --- a/TLB/src/ariane/tlb.py +++ b/TLB/src/ariane/tlb.py @@ -15,7 +15,10 @@ # Description: Translation Lookaside Buffer, SV39 # fully set-associative """ -from math import log +from math import log2 +from nmigen import Signal, Module, Cat, Const, Array +from nmigen.cli import verilog, rtlil + # SV39 defines three levels of page tables class TLBEntry: @@ -33,6 +36,7 @@ ASID_WIDTH = 1 from ptw import TLBUpdate, PTE + class TLB: def __init__(self): self.flush_i = Signal() # Flush signal @@ -50,10 +54,9 @@ class TLB: def elaborate(self, platform): m = Module() - tags = TLBEntry() # SV39 defines three levels of page tables - - content = Array([TLB() for i in range(TLB_ENTRIES)]) + tags = Array([TLBEntry() for i in range(TLB_ENTRIES)]) + content = Array([PTE() for i in range(TLB_ENTRIES)]) vpn2 = Signal(9) vpn1 = Signal(9) @@ -64,9 +67,9 @@ class TLB: #------------- # 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]), + m.d.comb += [ vpn0.eq(self.lu_vaddr_i[12:21]), + vpn1.eq(self.lu_vaddr_i[21:30]), + vpn2.eq(self.lu_vaddr_i[30:39]), ] for i in range(TLB_ENTRIES): @@ -74,23 +77,23 @@ class TLB: # first level match, this may be a giga page, # check the ASID flags as well with m.If(tags[i].valid & \ - tags[i].asid == lu_asid_i & \ - tags[i].vpn2 == vpn2): + (tags[i].asid == self.lu_asid_i) & \ + (tags[i].vpn2 == vpn2)): # second level with m.If (tags[i].is_1G): - m.d.sync += lu_content_o.eq(content[i]) - m.d.comb += [ lu_is_1G_o.eq(1), - lu_hit_o.eq(1), + m.d.sync += self.lu_content_o.eq(content[i]) + m.d.comb += [ self.lu_is_1G_o.eq(1), + self.lu_hit_o.eq(1), lu_hit[i].eq(1), ] # not a giga page hit so check further with m.Elif(vpn1 == tags[i].vpn1): # this could be a 2 mega page hit or a 4 kB hit # output accordingly - with m.If(tags[i].is_2M | vpn0 == tags[i].vpn0): - m.d.sync += lu_content_o.eq(content[i]) - m.d.comb += [ lu_is_2M_o.eq(tags[i].is_2M), - lu_hit_o.eq(1), + with m.If(tags[i].is_2M | (vpn0 == tags[i].vpn0)): + m.d.sync += self.lu_content_o.eq(content[i]) + m.d.comb += [ self.lu_is_2M_o.eq(tags[i].is_2M), + self.lu_hit_o.eq(1), lu_hit[i].eq(1), ] @@ -99,24 +102,24 @@ class TLB: # ------------------ for i in range(TLB_ENTRIES): - with m.If (flush_i): + with m.If (self.flush_i): # 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)): + with m.If (self.lu_asid_i == Const(0, ASID_WIDTH) | + (self.lu_asid_i == tags[i].asid)): m.d.sync += tags[i].valid.eq(0) # normal replacement - with m.Elif(update_i.valid & replace_en[i]): + with m.Elif(self.update_i.valid & replace_en[i]): m.d.sync += [ # update tag array - tags[i].asid.eq(update_i.asid), - tags[i].vpn2.eq(update_i.vpn [18:27]), - tags[i].vpn1.eq(update_i.vpn [9:18]), - tags[i].vpn0.eq(update_i.vpn[0:9]), - tags[i].is_1G.eq(update_i.is_1G), - tags[i].is_2M.eq(update_i.is_2M), + tags[i].asid.eq(self.update_i.asid), + tags[i].vpn2.eq(self.update_i.vpn [18:27]), + tags[i].vpn1.eq(self.update_i.vpn [9:18]), + tags[i].vpn0.eq(self.update_i.vpn[0:9]), + tags[i].is_1G.eq(self.update_i.is_1G), + tags[i].is_2M.eq(self.update_i.is_2M), tags[i].valid.eq(1), # and content as well - content[i].eq(update_i.content) + content[i].eq(self.update_i.content) ] # ----------------------------------------------- @@ -152,7 +155,7 @@ class TLB: LOG_TLB = int(log2(TLB_ENTRIES)) for i in range(TLB_ENTRIES): # we got a hit so update the pointer as it was least recently used - with m.If (lu_hit[i] & lu_access_i): + with m.If (lu_hit[i] & self.lu_access_i): # Set the nodes to the values we would expect for lvl in range(LOG_TLB): idx_base = (1<= 1), \ "ASID width must be at least 1" + return m + """ # Just for checking function int countSetBits(logic[TLB_ENTRIES-1:0] vector); @@ -217,3 +222,15 @@ class TLB: else $error("More then one TLB entry selected for next replace!"); """ + def ports(self): + return [self.flush_i, self.lu_access_i, + self.lu_asid_i, self.lu_vaddr_i, + self.lu_is_2M_o, self.lu_is_1G_o, self.lu_hit_o, + ] + self.lu_content_o.ports() + self.update_i.ports() + +if __name__ == '__main__': + tlb = TLB() + vl = rtlil.convert(tlb, ports=tlb.ports()) + with open("test_tlb.il", "w") as f: + f.write(vl) + -- 2.30.2