3 from ..memory
import _RangeMap
, MemoryMap
6 class RangeMapTestCase(unittest
.TestCase
):
8 range_map
= _RangeMap()
9 range_map
.insert(range(0,10), "a")
10 range_map
.insert(range(20,21), "c")
11 range_map
.insert(range(15,16), "b")
12 range_map
.insert(range(16,20), "q")
13 self
.assertEqual(range_map
._keys
, [
14 range(0,10), range(15,16), range(16,20), range(20,21)
17 def test_overlaps(self
):
18 range_map
= _RangeMap()
19 range_map
.insert(range(10,20), "a")
20 self
.assertEqual(range_map
.overlaps(range(5,15)), ["a"])
21 self
.assertEqual(range_map
.overlaps(range(15,25)), ["a"])
22 self
.assertEqual(range_map
.overlaps(range(5,25)), ["a"])
23 self
.assertEqual(range_map
.overlaps(range(0,3)), [])
24 self
.assertEqual(range_map
.overlaps(range(0,5)), [])
25 self
.assertEqual(range_map
.overlaps(range(25,30)), [])
27 def test_insert_wrong_overlap(self
):
28 range_map
= _RangeMap()
29 range_map
.insert(range(0,10), "a")
30 with self
.assertRaises(AssertionError):
31 range_map
.insert(range(5,15), "b")
34 range_map
= _RangeMap()
35 range_map
.insert(range(5,15), "a")
36 self
.assertEqual(range_map
.get(0), None)
37 self
.assertEqual(range_map
.get(5), "a")
38 self
.assertEqual(range_map
.get(10), "a")
39 self
.assertEqual(range_map
.get(14), "a")
40 self
.assertEqual(range_map
.get(15), None)
43 class MemoryMapTestCase(unittest
.TestCase
):
44 def test_wrong_addr_width(self
):
45 with self
.assertRaisesRegex(ValueError,
46 r
"Address width must be a positive integer, not -1"):
47 MemoryMap(addr_width
=-1, data_width
=8)
49 def test_wrong_data_width(self
):
50 with self
.assertRaisesRegex(ValueError,
51 r
"Data width must be a positive integer, not -1"):
52 MemoryMap(addr_width
=16, data_width
=-1)
54 def test_wrong_alignment(self
):
55 with self
.assertRaisesRegex(ValueError,
56 r
"Alignment must be a non-negative integer, not -1"):
57 MemoryMap(addr_width
=16, data_width
=8, alignment
=-1)
59 def test_add_resource(self
):
60 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
61 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
62 self
.assertEqual(memory_map
.add_resource("b", size
=2), (1, 3))
64 def test_add_resource_map_aligned(self
):
65 memory_map
= MemoryMap(addr_width
=16, data_width
=8, alignment
=1)
66 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 2))
67 self
.assertEqual(memory_map
.add_resource("b", size
=2), (2, 4))
69 def test_add_resource_explicit_aligned(self
):
70 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
71 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
72 self
.assertEqual(memory_map
.add_resource("b", size
=1, alignment
=1), (2, 4))
73 self
.assertEqual(memory_map
.add_resource("c", size
=2), (4, 6))
75 def test_add_resource_addr(self
):
76 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
77 self
.assertEqual(memory_map
.add_resource("a", size
=1, addr
=10), (10, 11))
78 self
.assertEqual(memory_map
.add_resource("b", size
=2), (11, 13))
80 def test_add_resource_wrong_address(self
):
81 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
82 with self
.assertRaisesRegex(ValueError,
83 r
"Address must be a non-negative integer, not -1"):
84 memory_map
.add_resource("a", size
=1, addr
=-1)
86 def test_add_resource_wrong_address_unaligned(self
):
87 memory_map
= MemoryMap(addr_width
=16, data_width
=8, alignment
=1)
88 with self
.assertRaisesRegex(ValueError,
89 r
"Explicitly specified address 0x1 must be a multiple of 0x2 bytes"):
90 memory_map
.add_resource("a", size
=1, addr
=1)
92 def test_add_resource_wrong_size(self
):
93 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
94 with self
.assertRaisesRegex(ValueError,
95 r
"Size must be a non-negative integer, not -1"):
96 memory_map
.add_resource("a", size
=-1)
98 def test_add_resource_wrong_alignment(self
):
99 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
100 with self
.assertRaisesRegex(ValueError,
101 r
"Alignment must be a non-negative integer, not -1"):
102 memory_map
.add_resource("a", size
=1, alignment
=-1)
104 def test_add_resource_wrong_out_of_bounds(self
):
105 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
106 with self
.assertRaisesRegex(ValueError,
107 r
"Address range 0x10000\.\.0x10001 out of bounds for memory map spanning "
108 r
"range 0x0\.\.0x10000 \(16 address bits\)"):
109 memory_map
.add_resource("a", addr
=0x10000, size
=1)
110 with self
.assertRaisesRegex(ValueError,
111 r
"Address range 0x0\.\.0x10001 out of bounds for memory map spanning "
112 r
"range 0x0\.\.0x10000 \(16 address bits\)"):
113 memory_map
.add_resource("a", size
=0x10001)
115 def test_add_resource_wrong_overlap(self
):
116 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
117 memory_map
.add_resource("a", size
=16)
118 with self
.assertRaisesRegex(ValueError,
119 r
"Address range 0xa\.\.0xb overlaps with resource 'a' at 0x0\.\.0x10"):
120 memory_map
.add_resource("b", size
=1, addr
=10)
122 def test_add_resource_wrong_twice(self
):
123 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
124 memory_map
.add_resource("a", size
=16)
125 with self
.assertRaisesRegex(ValueError,
126 r
"Resource 'a' is already added at address range 0x0..0x10"):
127 memory_map
.add_resource("a", size
=16)
129 def test_iter_resources(self
):
130 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
131 memory_map
.add_resource("a", size
=1)
132 memory_map
.add_resource("b", size
=2)
133 self
.assertEqual(list(memory_map
.resources()), [
138 def test_add_window(self
):
139 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
140 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
141 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8)),
143 self
.assertEqual(memory_map
.add_resource("b", size
=1), (0x800, 0x801))
145 def test_add_window_sparse(self
):
146 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
147 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8),
151 def test_add_window_dense(self
):
152 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
153 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8),
157 def test_add_window_wrong_window(self
):
158 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
159 with self
.assertRaisesRegex(TypeError,
160 r
"Window must be a MemoryMap, not 'a'"):
161 memory_map
.add_window("a")
163 def test_add_window_wrong_wider(self
):
164 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
165 with self
.assertRaisesRegex(ValueError,
166 r
"Window has data width 16, and cannot be added to a memory map "
167 r
"with data width 8"):
168 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=16))
170 def test_add_window_wrong_no_mode(self
):
171 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
172 with self
.assertRaisesRegex(ValueError,
173 r
"Address translation mode must be explicitly specified when adding "
174 r
"a window with data width 8 to a memory map with data width 16"):
175 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
177 def test_add_window_wrong_ratio(self
):
178 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
179 with self
.assertRaisesRegex(ValueError,
180 r
"Dense addressing cannot be used because the memory map data width "
181 r
"16 is not an integer multiple of window data width 7"):
182 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=7), sparse
=False)
184 def test_add_window_wrong_overlap(self
):
185 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
186 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
187 with self
.assertRaisesRegex(ValueError,
188 r
"Address range 0x200\.\.0x600 overlaps with window "
189 r
"<nmigen_soc\.memory\.MemoryMap object at .+?> at 0x0\.\.0x400"):
190 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8), addr
=0x200)
192 def test_add_window_wrong_twice(self
):
193 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
194 window
= MemoryMap(addr_width
=10, data_width
=8)
195 memory_map
.add_window(window
)
196 with self
.assertRaisesRegex(ValueError,
197 r
"Window <nmigen_soc\.memory\.MemoryMap object at .+?> is already added "
198 r
"at address range 0x0\.\.0x400"):
199 memory_map
.add_window(window
)
201 def test_iter_windows(self
):
202 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
203 window_1
= MemoryMap(addr_width
=10, data_width
=8)
204 memory_map
.add_window(window_1
, sparse
=False)
205 window_2
= MemoryMap(addr_width
=12, data_width
=16)
206 memory_map
.add_window(window_2
)
207 self
.assertEqual(list(memory_map
.windows()), [
208 (window_1
, (0, 0x200, 2)),
209 (window_2
, (0x1000, 0x2000, 1)),
212 def test_iter_window_patterns(self
):
213 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
214 window_1
= MemoryMap(addr_width
=10, data_width
=8)
215 memory_map
.add_window(window_1
, sparse
=False)
216 window_2
= MemoryMap(addr_width
=12, data_width
=16)
217 memory_map
.add_window(window_2
)
218 self
.assertEqual(list(memory_map
.window_patterns()), [
219 (window_1
, ("000000----------", 2)),
220 (window_2
, ("0001------------", 1)),
223 def test_align_to(self
):
224 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
225 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
226 self
.assertEqual(memory_map
.align_to(10), 0x400)
227 self
.assertEqual(memory_map
.add_resource("b", size
=16), (0x400, 0x410))
229 def test_align_to_wrong(self
):
230 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
231 with self
.assertRaisesRegex(ValueError,
232 r
"Alignment must be a non-negative integer, not -1"):
233 memory_map
.align_to(-1)
236 class MemoryMapDiscoveryTestCase(unittest
.TestCase
):
238 self
.root
= MemoryMap(addr_width
=32, data_width
=32)
240 self
.root
.add_resource(self
.res1
, size
=16)
241 self
.win1
= MemoryMap(addr_width
=16, data_width
=32)
242 self
.root
.add_window(self
.win1
)
244 self
.win1
.add_resource(self
.res2
, size
=32)
246 self
.win1
.add_resource(self
.res3
, size
=32)
248 self
.root
.add_resource(self
.res4
, size
=1)
249 self
.win2
= MemoryMap(addr_width
=16, data_width
=8)
250 self
.root
.add_window(self
.win2
, sparse
=True)
252 self
.win2
.add_resource(self
.res5
, size
=16)
253 self
.win3
= MemoryMap(addr_width
=16, data_width
=8)
254 self
.root
.add_window(self
.win3
, sparse
=False)
256 self
.win3
.add_resource(self
.res6
, size
=16)
258 def test_iter_all_resources(self
):
259 self
.assertEqual(list(self
.root
.all_resources()), [
260 (self
.res1
, (0x00000000, 0x00000010, 32)),
261 (self
.res2
, (0x00010000, 0x00010020, 32)),
262 (self
.res3
, (0x00010020, 0x00010040, 32)),
263 (self
.res4
, (0x00020000, 0x00020001, 32)),
264 (self
.res5
, (0x00030000, 0x00030010, 8)),
265 (self
.res6
, (0x00040000, 0x00040004, 32)),
268 def test_find_resource(self
):
269 for res
, loc
in self
.root
.all_resources():
270 self
.assertEqual(self
.root
.find_resource(res
), loc
)
272 def test_find_resource_wrong(self
):
273 with self
.assertRaises(KeyError) as error
:
274 self
.root
.find_resource("resNA")
275 self
.assertEqual(error
.exception
.args
, ("resNA",))
277 def test_decode_address(self
):
278 for res
, (start
, end
, width
) in self
.root
.all_resources():
279 self
.assertEqual(self
.root
.decode_address(start
), res
)
280 self
.assertEqual(self
.root
.decode_address(end
- 1), res
)
282 def test_decode_address_missing(self
):
283 self
.assertIsNone(self
.root
.decode_address(0x00000100))