From: Luke Kenneth Casson Leighton Date: Sun, 13 Sep 2020 11:25:24 +0000 (+0100) Subject: sort out ariane PLRU, rename/clarify X-Git-Tag: semi_working_ecp5~78 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1e2ec5e18a6919d33ae70806dc1bdaf1808619c3;p=soc.git sort out ariane PLRU, rename/clarify --- diff --git a/src/soc/experiment/dcache.py b/src/soc/experiment/dcache.py index fd90a145..bc2f3d37 100644 --- a/src/soc/experiment/dcache.py +++ b/src/soc/experiment/dcache.py @@ -1837,5 +1837,5 @@ if __name__ == '__main__': mem.append((i*2)| ((i*2+1)<<32)) test_dcache(mem, dcache_sim, "") - #test_dcache(None, dcache_random_sim, "random") + test_dcache(None, dcache_random_sim, "random") diff --git a/src/soc/experiment/plru.py b/src/soc/experiment/plru.py index baa68ce2..c8a59b39 100644 --- a/src/soc/experiment/plru.py +++ b/src/soc/experiment/plru.py @@ -1,6 +1,8 @@ # based on microwatt plru.vhdl from nmigen import Elaboratable, Signal, Array, Module +from nmigen.cli import rtlil + class PLRU(Elaboratable): @@ -14,7 +16,7 @@ class PLRU(Elaboratable): m = Module() comb, sync = m.d.comb, m.d.sync - tree = Array(Signal() for i in range(self.BITS)) + tree = Array(Signal(name="tree%d" % i) for i in range(self.BITS)) # XXX Check if we can turn that into a little ROM instead that # takes the tree bit vector and returns the LRU. See if it's better @@ -52,3 +54,14 @@ class PLRU(Elaboratable): node = node_next return m + + def ports(self): + return [self.acc_en, self.lru_o, self.acc] + +if __name__ == '__main__': + dut = PLRU(3) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_plru.il", "w") as f: + f.write(vl) + + diff --git a/src/unused/TLB/ariane/plru.py b/src/unused/TLB/ariane/plru.py index 25d208ae..70e21268 100644 --- a/src/unused/TLB/ariane/plru.py +++ b/src/unused/TLB/ariane/plru.py @@ -1,6 +1,9 @@ -from nmigen import Signal, Module, Cat, Const +# based on ariane plru, from tlb.sv + +from nmigen import Signal, Module, Cat, Const, Repl from nmigen.hdl.ir import Elaboratable -from math import log2 +from nmigen.cli import rtlil +from nmigen.utils import log2_int class PLRU(Elaboratable): @@ -17,50 +20,51 @@ class PLRU(Elaboratable): ... ... ... ... """ - def __init__(self, entries): - self.entries = entries - self.lu_hit = Signal(entries) - self.replace_en_o = Signal(entries) - self.lu_access_i = Signal() - # Tree (bit per entry) - self.TLBSZ = 2*(self.entries-1) - self.plru_tree = Signal(self.TLBSZ) - self.plru_tree_o = Signal(self.TLBSZ) + def __init__(self, BITS): + self.BITS = BITS + self.acc_en = Signal(BITS) + self.lru_o = Signal(BITS) + self.acc_i = Signal() def elaborate(self, platform=None): m = Module() + # Tree (bit per entry) + TLBSZ = 2*(self.BITS-1) + plru_tree = Signal(TLBSZ) + # Just predefine which nodes will be set/cleared # E.g. for a TLB with 8 entries, the for-loop is semantically # equivalent to the following pseudo-code: # unique case (1'b1) - # lu_hit[7]: plru_tree[0, 2, 6] = {1, 1, 1}; - # lu_hit[6]: plru_tree[0, 2, 6] = {1, 1, 0}; - # lu_hit[5]: plru_tree[0, 2, 5] = {1, 0, 1}; - # lu_hit[4]: plru_tree[0, 2, 5] = {1, 0, 0}; - # lu_hit[3]: plru_tree[0, 1, 4] = {0, 1, 1}; - # lu_hit[2]: plru_tree[0, 1, 4] = {0, 1, 0}; - # lu_hit[1]: plru_tree[0, 1, 3] = {0, 0, 1}; - # lu_hit[0]: plru_tree[0, 1, 3] = {0, 0, 0}; + # acc_en[7]: plru_tree[0, 2, 6] = {1, 1, 1}; + # acc_en[6]: plru_tree[0, 2, 6] = {1, 1, 0}; + # acc_en[5]: plru_tree[0, 2, 5] = {1, 0, 1}; + # acc_en[4]: plru_tree[0, 2, 5] = {1, 0, 0}; + # acc_en[3]: plru_tree[0, 1, 4] = {0, 1, 1}; + # acc_en[2]: plru_tree[0, 1, 4] = {0, 1, 0}; + # acc_en[1]: plru_tree[0, 1, 3] = {0, 0, 1}; + # acc_en[0]: plru_tree[0, 1, 3] = {0, 0, 0}; # default: begin /* No hit */ end # endcase - LOG_TLB = int(log2(self.entries)) - print(LOG_TLB) - for i in range(self.entries): + + LOG_TLB = log2_int(self.BITS) + hit = Signal(self.BITS) + m.d.comb += hit.eq(Repl(self.acc_i, self.BITS) & self.acc_en) + + for i in range(self.BITS): # we got a hit so update the pointer as it was least recently used - hit = Signal(reset_less=True) - m.d.comb += hit.eq(self.lu_hit[i] & self.lu_access_i) - with m.If(hit): + with m.If(hit[i]): # Set the nodes to the values we would expect for lvl in range(LOG_TLB): idx_base = (1 << lvl)-1 # lvl0 <=> MSB, lvl1 <=> MSB-1, ... shift = LOG_TLB - lvl - new_idx = Const(~((i >> (shift-1)) & 1), (1, False)) + new_idx = Const(~((i >> (shift-1)) & 1), 1) plru_idx = idx_base + (i >> shift) print("plru", i, lvl, hex(idx_base), plru_idx, shift, new_idx) - m.d.comb += self.plru_tree_o[plru_idx].eq(new_idx) + m.d.sync += plru_tree[plru_idx].eq(new_idx) # Decode tree to write enable signals # Next for-loop basically creates the following logic for e.g. @@ -77,7 +81,7 @@ class PLRU(Elaboratable): # the corresponding bit of the entry's index, this is # the next entry to replace. replace = [] - for i in range(self.entries): + for i in range(self.BITS): en = [] for lvl in range(LOG_TLB): idx_base = (1 << lvl)-1 @@ -87,20 +91,26 @@ class PLRU(Elaboratable): plru_idx = idx_base + (i >> shift) plru = Signal(reset_less=True, name="plru-%d-%d-%d" % (i, lvl, plru_idx)) - m.d.comb += plru.eq(self.plru_tree[plru_idx]) - # en &= plru_tree_q[idx_base + (i>>shift)] == new_idx; + m.d.comb += plru.eq(plru_tree[plru_idx]) if new_idx: - en.append(~plru) # yes inverted (using bool()) + en.append(~plru) # yes inverted (using bool() below) else: - en.append(plru) # yes inverted (using bool()) - print("plru", i, en) + en.append(plru) # yes inverted (using bool() below) + print("plru replace", i, en) # boolean logic manipulation: # plru0 & plru1 & plru2 == ~(~plru0 | ~plru1 | ~plru2) replace.append(~Cat(*en).bool()) - m.d.comb += self.replace_en_o.eq(Cat(*replace)) + m.d.comb += self.lru_o.eq(Cat(*replace)) return m def ports(self): - return [self.entries, self.lu_hit, self.replace_en_o, - self.lu_access_i, self.plru_tree, self.plru_tree_o] + return [self.acc_en, self.lru_o, self.acc_i] + + +if __name__ == '__main__': + dut = PLRU(4) + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_plru.il", "w") as f: + f.write(vl) +