whoops new node not to be calculated at end
[soc.git] / src / soc / experiment / plru.py
1 # based on microwatt plru.vhdl
2
3 from nmigen import Elaboratable, Signal, Array, Module
4
5 class PLRU(Elaboratable):
6
7 def __init__(self, BITS=2):
8 self.BITS = BITS
9 self.acc = Signal(BITS)
10 self.acc_en = Signal()
11 self.lru_o = Signal(BITS)
12
13 def elaborate(self, platform):
14 m = Module()
15 comb, sync = m.d.comb, m.d.sync
16
17 tree = Array(Signal() for i in range(self.BITS))
18
19 # XXX Check if we can turn that into a little ROM instead that
20 # takes the tree bit vector and returns the LRU. See if it's better
21 # in term of FPGA resouces usage...
22 node = Signal(self.BITS)
23 for i in range(self.BITS):
24 node_next = Signal(self.BITS)
25 node2 = Signal(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 comb += node2.eq(node << 1)
31 else:
32 comb += node2.eq(node)
33 if i != self.BITS-1:
34 with m.If(tree[node]):
35 comb += node_next.eq(node2 + 2)
36 with m.Else():
37 comb += node_next.eq(node2 + 1)
38 node = node_next
39
40 with m.If(self.acc_en):
41 node = Signal(self.BITS)
42 for i in range(self.BITS):
43 node_next = Signal(self.BITS)
44 node2 = Signal(self.BITS)
45 # report "GET: i:" & integer'image(i) & " node:" &
46 # integer'image(node) & " val:" & Signal()'image(tree(node))
47 abit = self.acc[self.BITS-1-i]
48 sync += tree[node].eq(~abit)
49 if i != self.BITS-1:
50 comb += node2.eq(node << 1)
51 else:
52 comb += node2.eq(node)
53 if i != self.BITS-1:
54 with m.If(abit):
55 comb += node_next.eq(node2 + 2)
56 with m.Else():
57 comb += node_next.eq(node2 + 1)
58 node = node_next
59
60 return m