radix: reading first page table entry
[soc.git] / src / soc / experiment / plru.py
1 # based on microwatt plru.vhdl
2
3 from nmigen import Elaboratable, Signal, Array, Module, Mux, Const
4 from nmigen.cli import rtlil
5
6
7 class PLRU(Elaboratable):
8
9 def __init__(self, BITS=2):
10 self.BITS = BITS
11 self.acc_i = Signal(BITS)
12 self.acc_en = Signal()
13 self.lru_o = Signal(BITS)
14
15 def elaborate(self, platform):
16 m = Module()
17 comb, sync = m.d.comb, m.d.sync
18
19 tree = Array(Signal(name="tree%d" % i) for i in range(self.BITS))
20
21 # XXX Check if we can turn that into a little ROM instead that
22 # takes the tree bit vector and returns the LRU. See if it's better
23 # in term of FPGA resouces usage...
24 node = Const(0, self.BITS)
25 for i in range(self.BITS):
26 # report "GET: i:" & integer'image(i) & " node:" &
27 # integer'image(node) & " val:" & Signal()'image(tree(node))
28 comb += self.lru_o[self.BITS-1-i].eq(tree[node])
29 if i != self.BITS-1:
30 node_next = Signal(self.BITS)
31 node2 = Signal(self.BITS)
32 comb += node2.eq(node << 1)
33 comb += node_next.eq(Mux(tree[node2], node2+2, node2+1))
34 node = node_next
35
36 with m.If(self.acc_en):
37 node = Const(0, self.BITS)
38 for i in range(self.BITS):
39 # report "GET: i:" & integer'image(i) & " node:" &
40 # integer'image(node) & " val:" & Signal()'image(tree(node))
41 abit = self.acc_i[self.BITS-1-i]
42 sync += tree[node].eq(~abit)
43 if i != self.BITS-1:
44 node_next = Signal(self.BITS)
45 node2 = Signal(self.BITS)
46 comb += node2.eq(node << 1)
47 comb += node_next.eq(Mux(abit, node2+2, node2+1))
48 node = node_next
49
50 return m
51
52 def ports(self):
53 return [self.acc_en, self.lru_o, self.acc_i]
54
55 if __name__ == '__main__':
56 dut = PLRU(2)
57 vl = rtlil.convert(dut, ports=dut.ports())
58 with open("test_plru.il", "w") as f:
59 f.write(vl)
60
61