92b8fc1480b23b04d72686726e51bbea7d62341c
1 # based on microwatt plru.vhdl
3 from nmigen
import Elaboratable
, Signal
, Array
, Module
, Mux
, Const
, Cat
4 from nmigen
.cli
import rtlil
5 from nmigen
.lib
.coding
import Decoder
8 class PLRU(Elaboratable
):
10 def __init__(self
, BITS
=2):
12 self
.acc_i
= Signal(BITS
)
13 self
.acc_en
= Signal()
14 self
.lru_o
= Signal(BITS
)
16 def elaborate(self
, platform
):
18 comb
, sync
= m
.d
.comb
, m
.d
.sync
20 tree
= Array(Signal(name
="tree%d" % i
) for i
in range(self
.BITS
))
22 # XXX Check if we can turn that into a little ROM instead that
23 # takes the tree bit vector and returns the LRU. See if it's better
24 # in term of FPGA resouces usage...
25 node
= Const(0, self
.BITS
)
26 for i
in range(self
.BITS
):
27 # report "GET: i:" & integer'image(i) & " node:" &
28 # integer'image(node) & " val:" & Signal()'image(tree(node))
29 comb
+= self
.lru_o
[self
.BITS
-1-i
].eq(tree
[node
])
31 node_next
= Signal(self
.BITS
)
32 node2
= Signal(self
.BITS
)
33 comb
+= node2
.eq(node
<< 1)
34 comb
+= node_next
.eq(Mux(tree
[node2
], node2
+2, node2
+1))
37 with m
.If(self
.acc_en
):
38 node
= Const(0, self
.BITS
)
39 for i
in range(self
.BITS
):
40 # report "GET: i:" & integer'image(i) & " node:" &
41 # integer'image(node) & " val:" & Signal()'image(tree(node))
42 abit
= self
.acc_i
[self
.BITS
-1-i
]
43 sync
+= tree
[node
].eq(~abit
)
45 node_next
= Signal(self
.BITS
)
46 node2
= Signal(self
.BITS
)
47 comb
+= node2
.eq(node
<< 1)
48 comb
+= node_next
.eq(Mux(abit
, node2
+2, node2
+1))
54 return [self
.acc_en
, self
.lru_o
, self
.acc_i
]
57 class PLRUs(Elaboratable
):
58 def __init__(self
, n_plrus
, n_bits
):
59 self
.n_plrus
= n_plrus
62 self
.way
= Signal(n_bits
)
63 self
.index
= Signal(n_plrus
.bit_length())
64 self
.isel
= Signal(n_plrus
.bit_length())
65 self
.o_index
= Signal(n_bits
)
67 def elaborate(self
, platform
):
76 # Binary-to-Unary one-hot, enabled by valid
77 m
.submodules
.te
= te
= Decoder(self
.n_plrus
)
78 comb
+= te
.n
.eq(~self
.valid
)
79 comb
+= te
.i
.eq(self
.index
)
81 out
= Array(Signal(self
.n_bits
, name
="plru_out%d" % x
) \
82 for x
in range(self
.n_plrus
))
84 for i
in range(self
.n_plrus
):
86 m
.submodules
["plru_%d" % i
] = plru
= PLRU(self
.n_bits
)
88 comb
+= plru
.acc_en
.eq(te
.o
[i
])
89 comb
+= plru
.acc_i
.eq(self
.way
)
90 comb
+= out
[i
].eq(plru
.lru_o
)
92 # select output based on index
93 comb
+= self
.o_index
.eq(out
[self
.isel
])
98 return [self
.valid
, self
.way
, self
.index
, self
.isel
, self
.o_index
]
101 if __name__
== '__main__':
103 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
104 with
open("test_plru.il", "w") as f
:
109 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
110 with
open("test_plrus.il", "w") as f
: