7f42319f0e8b7a310d690804da8cc27956358b4d
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))
73 memory_map
.add_resource(
74 "b", size
=1, alignment
=1), (2, 4))
75 self
.assertEqual(memory_map
.add_resource("c", size
=2), (4, 6))
77 def test_add_resource_addr(self
):
78 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
80 memory_map
.add_resource(
81 "a", size
=1, addr
=10), (10, 11))
82 self
.assertEqual(memory_map
.add_resource("b", size
=2), (11, 13))
84 def test_add_resource_wrong_address(self
):
85 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
86 with self
.assertRaisesRegex(ValueError,
87 r
"Address must be a non-negative integer, not -1"):
88 memory_map
.add_resource("a", size
=1, addr
=-1)
90 def test_add_resource_wrong_address_unaligned(self
):
91 memory_map
= MemoryMap(addr_width
=16, data_width
=8, alignment
=1)
92 with self
.assertRaisesRegex(ValueError,
93 r
"Explicitly specified address 0x1 must be "
94 r
"a multiple of 0x2 bytes"):
95 memory_map
.add_resource("a", size
=1, addr
=1)
97 def test_add_resource_wrong_size(self
):
98 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
99 with self
.assertRaisesRegex(ValueError,
100 r
"Size must be a non-negative integer, not -1"):
101 memory_map
.add_resource("a", size
=-1)
103 def test_add_resource_wrong_alignment(self
):
104 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
105 with self
.assertRaisesRegex(ValueError,
106 r
"Alignment must be a non-negative integer, not -1"):
107 memory_map
.add_resource("a", size
=1, alignment
=-1)
109 def test_add_resource_wrong_out_of_bounds(self
):
110 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
111 with self
.assertRaisesRegex(ValueError,
112 r
"Address range 0x10000\.\.0x10001 out of bounds for memory "
113 r
"map spanning range 0x0\.\.0x10000 \(16 address bits\)"):
114 memory_map
.add_resource("a", addr
=0x10000, size
=1)
115 with self
.assertRaisesRegex(ValueError,
116 r
"Address range 0x0\.\.0x10001 out of bounds for memory map "
117 r
"spanning range 0x0\.\.0x10000 \(16 address bits\)"):
118 memory_map
.add_resource("a", size
=0x10001)
120 def test_add_resource_wrong_overlap(self
):
121 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
122 memory_map
.add_resource("a", size
=16)
123 with self
.assertRaisesRegex(ValueError,
124 r
"Address range 0xa\.\.0xb overlaps with resource "
125 r
"'a' at 0x0\.\.0x10"):
126 memory_map
.add_resource("b", size
=1, addr
=10)
128 def test_add_resource_wrong_twice(self
):
129 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
130 memory_map
.add_resource("a", size
=16)
131 with self
.assertRaisesRegex(ValueError,
132 r
"Resource 'a' is already added at address range 0x0..0x10"):
133 memory_map
.add_resource("a", size
=16)
135 def test_iter_resources(self
):
136 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
137 memory_map
.add_resource("a", size
=1)
138 memory_map
.add_resource("b", size
=2)
139 self
.assertEqual(list(memory_map
.resources()), [
144 def test_add_window(self
):
145 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
146 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
147 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
150 self
.assertEqual(memory_map
.add_resource("b", size
=1), (0x800, 0x801))
152 def test_add_window_sparse(self
):
153 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
154 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
159 def test_add_window_dense(self
):
160 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
161 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
166 def test_add_window_wrong_window(self
):
167 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
168 with self
.assertRaisesRegex(TypeError,
169 r
"Window must be a MemoryMap, not 'a'"):
170 memory_map
.add_window("a")
172 def test_add_window_wrong_wider(self
):
173 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
174 with self
.assertRaisesRegex(ValueError,
175 r
"Window has data width 16, and cannot be added to a memory "
176 r
"map with data width 8"):
177 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=16))
179 def test_add_window_wrong_no_mode(self
):
180 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
181 with self
.assertRaisesRegex(ValueError,
182 r
"Address translation mode must be explicitly specified "
183 r
"when adding a window with data width 8 to a memory map "
184 r
"with data width 16"):
185 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
187 def test_add_window_wrong_ratio(self
):
188 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
189 with self
.assertRaisesRegex(ValueError,
190 r
"Dense addressing cannot be used because the memory map "
191 r
"data width 16 is not an integer multiple of window data "
193 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=7),
196 def test_add_window_wrong_overlap(self
):
197 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
198 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
199 with self
.assertRaisesRegex(ValueError,
200 r
"Address range 0x200\.\.0x600 overlaps with window "
201 r
"<nmigen_soc\.memory\.MemoryMap object at .+?> "
203 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8),
206 def test_add_window_wrong_twice(self
):
207 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
208 window
= MemoryMap(addr_width
=10, data_width
=8)
209 memory_map
.add_window(window
)
210 with self
.assertRaisesRegex(ValueError,
211 r
"Window <nmigen_soc\.memory\.MemoryMap object at .+?> is "
212 r
"already added at address range 0x0\.\.0x400"):
213 memory_map
.add_window(window
)
215 def test_iter_windows(self
):
216 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
217 window_1
= MemoryMap(addr_width
=10, data_width
=8)
218 memory_map
.add_window(window_1
, sparse
=False)
219 window_2
= MemoryMap(addr_width
=12, data_width
=16)
220 memory_map
.add_window(window_2
)
221 self
.assertEqual(list(memory_map
.windows()), [
222 (window_1
, (0, 0x200, 2)),
223 (window_2
, (0x1000, 0x2000, 1)),
226 def test_iter_window_patterns(self
):
227 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
228 window_1
= MemoryMap(addr_width
=10, data_width
=8)
229 memory_map
.add_window(window_1
, sparse
=False)
230 window_2
= MemoryMap(addr_width
=12, data_width
=16)
231 memory_map
.add_window(window_2
)
232 self
.assertEqual(list(memory_map
.window_patterns()), [
233 (window_1
, ("000000----------", 2)),
234 (window_2
, ("0001------------", 1)),
237 def test_align_to(self
):
238 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
239 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
240 self
.assertEqual(memory_map
.align_to(10), 0x400)
241 self
.assertEqual(memory_map
.add_resource("b", size
=16), (0x400, 0x410))
243 def test_align_to_wrong(self
):
244 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
245 with self
.assertRaisesRegex(ValueError,
246 r
"Alignment must be a non-negative integer, not -1"):
247 memory_map
.align_to(-1)
250 class MemoryMapDiscoveryTestCase(unittest
.TestCase
):
252 self
.root
= MemoryMap(addr_width
=32, data_width
=32)
254 self
.root
.add_resource(self
.res1
, size
=16)
255 self
.win1
= MemoryMap(addr_width
=16, data_width
=32)
256 self
.root
.add_window(self
.win1
)
258 self
.win1
.add_resource(self
.res2
, size
=32)
260 self
.win1
.add_resource(self
.res3
, size
=32)
262 self
.root
.add_resource(self
.res4
, size
=1)
263 self
.win2
= MemoryMap(addr_width
=16, data_width
=8)
264 self
.root
.add_window(self
.win2
, sparse
=True)
266 self
.win2
.add_resource(self
.res5
, size
=16)
267 self
.win3
= MemoryMap(addr_width
=16, data_width
=8)
268 self
.root
.add_window(self
.win3
, sparse
=False)
270 self
.win3
.add_resource(self
.res6
, size
=16)
272 def test_iter_all_resources(self
):
273 self
.assertEqual(list(self
.root
.all_resources()), [
274 (self
.res1
, (0x00000000, 0x00000010, 32)),
275 (self
.res2
, (0x00010000, 0x00010020, 32)),
276 (self
.res3
, (0x00010020, 0x00010040, 32)),
277 (self
.res4
, (0x00020000, 0x00020001, 32)),
278 (self
.res5
, (0x00030000, 0x00030010, 8)),
279 (self
.res6
, (0x00040000, 0x00040004, 32)),
282 def test_find_resource(self
):
283 for res
, loc
in self
.root
.all_resources():
284 self
.assertEqual(self
.root
.find_resource(res
), loc
)
286 def test_find_resource_wrong(self
):
287 with self
.assertRaises(KeyError) as error
:
288 self
.root
.find_resource("resNA")
289 self
.assertEqual(error
.exception
.args
, ("resNA",))
291 def test_decode_address(self
):
292 for res
, (start
, end
, width
) in self
.root
.all_resources():
293 self
.assertEqual(self
.root
.decode_address(start
), res
)
294 self
.assertEqual(self
.root
.decode_address(end
- 1), res
)
296 def test_decode_address_missing(self
):
297 self
.assertIsNone(self
.root
.decode_address(0x00000100))