49b8599b4ce9dee56747a00faf7e747971519f36
1 # SPDX-License-Identifier: LGPL-3-or-later
2 # Copyright 2022 Jacob Lifshay
5 from nmigen
.hdl
.ast
import (AnySeq
, Assert
, Signal
, Assume
, Const
,
6 unsigned
, AnyConst
, Value
)
7 from nmigen
.hdl
.dsl
import Module
8 from nmutil
.formaltest
import FHDLTestCase
9 from nmutil
.plru
import PLRU
, PLRUs
10 from nmutil
.sim_util
import write_il
11 from nmutil
.plain_data
import plain_data
15 class PrettyPrintState
:
16 __slots__
= "indent", "file", "at_line_start"
18 def __init__(self
, indent
=0, file=None, at_line_start
=True):
21 self
.at_line_start
= at_line_start
23 def write(self
, text
):
27 self
.at_line_start
= True
28 elif self
.at_line_start
:
29 self
.at_line_start
= False
30 print(" " * self
.indent
, file=self
.file, end
='')
31 print(ch
, file=self
.file, end
='')
36 __slots__
= "state", "left_child", "right_child"
38 def __init__(self
, state
, left_child
=None, right_child
=None):
39 # type: (Signal, PLRUNode | None, PLRUNode | None) -> None
41 self
.left_child
= left_child
42 self
.right_child
= right_child
44 def __pretty_print(self
, state
):
45 # type: (PrettyPrintState) -> None
46 state
.write("PLRUNode(")
48 state
.write(f
"state={self.state!r},\n")
49 state
.write("left_child=")
50 if self
.left_child
is None:
53 self
.left_child
.__pretty
_print
(state
)
54 state
.write(",\nright_child=")
55 if self
.right_child
is None:
58 self
.right_child
.__pretty
_print
(state
)
62 def pretty_print(self
, file=None):
63 self
.__pretty
_print
(PrettyPrintState(file=file))
65 def set_states_from_index(self
, m
, index
):
66 # type: (Module, Value) -> None
67 m
.d
.sync
+= self
.state
.eq(index
[-1])
69 if self
.left_child
is not None:
70 self
.left_child
.set_states_from_index(m
, index
[:-1])
72 if self
.right_child
is not None:
73 self
.right_child
.set_states_from_index(m
, index
[:-1])
76 class TestPLRU(FHDLTestCase
):
77 @unittest.skip("not finished yet")
81 # FIXME: figure out what BITS is supposed to mean -- I would have
82 # expected it to be the number of cache ways, or the number of state
83 # bits in PLRU, but it's neither of those, making me think whoever
84 # converted the code botched their math.
86 # Until that's figured out, this test is broken.
89 write_il(self
, dut
, ports
=dut
.ports())
91 nodes
= [PLRUNode(Signal(name
=f
"state_{i}")) for i
in range(dut
.TLBSZ
)]
92 self
.assertEqual(len(dut
._plru
_tree
), len(nodes
))
93 for i
in range(1, dut
.TLBSZ
):
94 parent
= (i
+ 1) // 2 - 1
96 nodes
[parent
].left_child
= nodes
[i
]
98 nodes
[parent
].right_child
= nodes
[i
]
99 m
.d
.comb
+= Assert(nodes
[i
].state
== dut
._plru
_tree
[i
])
101 in_index
= Signal(range(BITS
))
104 in_index
.eq(AnySeq(range(BITS
))),
105 Assume(in_index
< BITS
),
106 dut
.acc_i
.eq(1 << in_index
),
107 dut
.acc_en
.eq(AnySeq(1)),
110 with m
.If(dut
.acc_en
):
111 nodes
[0].set_states_from_index(m
, in_index
)
113 nodes
[0].pretty_print()
115 m
.submodules
.dut
= dut
116 self
.assertFormal(m
, mode
="prove")
118 def test_bits_1(self
):
121 def test_bits_2(self
):
124 def test_bits_3(self
):
127 def test_bits_4(self
):
130 def test_bits_5(self
):
133 def test_bits_6(self
):
136 def test_bits_7(self
):
139 def test_bits_8(self
):
142 def test_bits_9(self
):
145 def test_bits_10(self
):
148 def test_bits_11(self
):
151 def test_bits_12(self
):
154 def test_bits_13(self
):
157 def test_bits_14(self
):
160 def test_bits_15(self
):
163 def test_bits_16(self
):
167 if __name__
== "__main__":