1 # based on microwatt plru.vhdl
3 from nmigen
import Elaboratable
, Signal
, Array
, Module
, Mux
, Const
4 from nmigen
.cli
import rtlil
7 class PLRU(Elaboratable
):
9 def __init__(self
, BITS
=2):
11 self
.acc_i
= Signal(BITS
)
12 self
.acc_en
= Signal()
13 self
.lru_o
= Signal(BITS
)
15 def elaborate(self
, platform
):
17 comb
, sync
= m
.d
.comb
, m
.d
.sync
19 tree
= Array(Signal(name
="tree%d" % i
) for i
in range(self
.BITS
))
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
])
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))
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
)
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))
53 return [self
.acc_en
, self
.lru_o
, self
.acc_i
]
55 if __name__
== '__main__':
57 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
58 with
open("test_plru.il", "w") as f
: