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 "
90 r
"a multiple of 0x2 bytes"):
91 memory_map
.add_resource("a", size
=1, addr
=1)
93 def test_add_resource_wrong_size(self
):
94 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
95 with self
.assertRaisesRegex(ValueError,
96 r
"Size must be a non-negative integer, not -1"):
97 memory_map
.add_resource("a", size
=-1)
99 def test_add_resource_wrong_alignment(self
):
100 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
101 with self
.assertRaisesRegex(ValueError,
102 r
"Alignment must be a non-negative integer, not -1"):
103 memory_map
.add_resource("a", size
=1, alignment
=-1)
105 def test_add_resource_wrong_out_of_bounds(self
):
106 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
107 with self
.assertRaisesRegex(ValueError,
108 r
"Address range 0x10000\.\.0x10001 out of bounds for memory "
109 r
"map spanning range 0x0\.\.0x10000 \(16 address bits\)"):
110 memory_map
.add_resource("a", addr
=0x10000, size
=1)
111 with self
.assertRaisesRegex(ValueError,
112 r
"Address range 0x0\.\.0x10001 out of bounds for memory map "
113 r
"spanning range 0x0\.\.0x10000 \(16 address bits\)"):
114 memory_map
.add_resource("a", size
=0x10001)
116 def test_add_resource_wrong_overlap(self
):
117 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
118 memory_map
.add_resource("a", size
=16)
119 with self
.assertRaisesRegex(ValueError,
120 r
"Address range 0xa\.\.0xb overlaps with resource "
121 r
"'a' at 0x0\.\.0x10"):
122 memory_map
.add_resource("b", size
=1, addr
=10)
124 def test_add_resource_wrong_twice(self
):
125 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
126 memory_map
.add_resource("a", size
=16)
127 with self
.assertRaisesRegex(ValueError,
128 r
"Resource 'a' is already added at address range 0x0..0x10"):
129 memory_map
.add_resource("a", size
=16)
131 def test_iter_resources(self
):
132 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
133 memory_map
.add_resource("a", size
=1)
134 memory_map
.add_resource("b", size
=2)
135 self
.assertEqual(list(memory_map
.resources()), [
140 def test_add_window(self
):
141 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
142 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
143 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
146 self
.assertEqual(memory_map
.add_resource("b", size
=1), (0x800, 0x801))
148 def test_add_window_sparse(self
):
149 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
150 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
155 def test_add_window_dense(self
):
156 memory_map
= MemoryMap(addr_width
=16, data_width
=32)
157 self
.assertEqual(memory_map
.add_window(MemoryMap(addr_width
=10,
162 def test_add_window_wrong_window(self
):
163 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
164 with self
.assertRaisesRegex(TypeError,
165 r
"Window must be a MemoryMap, not 'a'"):
166 memory_map
.add_window("a")
168 def test_add_window_wrong_wider(self
):
169 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
170 with self
.assertRaisesRegex(ValueError,
171 r
"Window has data width 16, and cannot be added to a memory "
172 r
"map with data width 8"):
173 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=16))
175 def test_add_window_wrong_no_mode(self
):
176 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
177 with self
.assertRaisesRegex(ValueError,
178 r
"Address translation mode must be explicitly specified "
179 r
"when adding a window with data width 8 to a memory map "
180 r
"with data width 16"):
181 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
183 def test_add_window_wrong_ratio(self
):
184 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
185 with self
.assertRaisesRegex(ValueError,
186 r
"Dense addressing cannot be used because the memory map "
187 r
"data width 16 is not an integer multiple of window data "
189 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=7),
192 def test_add_window_wrong_overlap(self
):
193 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
194 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8))
195 with self
.assertRaisesRegex(ValueError,
196 r
"Address range 0x200\.\.0x600 overlaps with window "
197 r
"<nmigen_soc\.memory\.MemoryMap object at .+?> "
199 memory_map
.add_window(MemoryMap(addr_width
=10, data_width
=8),
202 def test_add_window_wrong_twice(self
):
203 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
204 window
= MemoryMap(addr_width
=10, data_width
=8)
205 memory_map
.add_window(window
)
206 with self
.assertRaisesRegex(ValueError,
207 r
"Window <nmigen_soc\.memory\.MemoryMap object at .+?> is "
208 r
"already added at address range 0x0\.\.0x400"):
209 memory_map
.add_window(window
)
211 def test_iter_windows(self
):
212 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
213 window_1
= MemoryMap(addr_width
=10, data_width
=8)
214 memory_map
.add_window(window_1
, sparse
=False)
215 window_2
= MemoryMap(addr_width
=12, data_width
=16)
216 memory_map
.add_window(window_2
)
217 self
.assertEqual(list(memory_map
.windows()), [
218 (window_1
, (0, 0x200, 2)),
219 (window_2
, (0x1000, 0x2000, 1)),
222 def test_iter_window_patterns(self
):
223 memory_map
= MemoryMap(addr_width
=16, data_width
=16)
224 window_1
= MemoryMap(addr_width
=10, data_width
=8)
225 memory_map
.add_window(window_1
, sparse
=False)
226 window_2
= MemoryMap(addr_width
=12, data_width
=16)
227 memory_map
.add_window(window_2
)
228 self
.assertEqual(list(memory_map
.window_patterns()), [
229 (window_1
, ("000000----------", 2)),
230 (window_2
, ("0001------------", 1)),
233 def test_align_to(self
):
234 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
235 self
.assertEqual(memory_map
.add_resource("a", size
=1), (0, 1))
236 self
.assertEqual(memory_map
.align_to(10), 0x400)
237 self
.assertEqual(memory_map
.add_resource("b", size
=16), (0x400, 0x410))
239 def test_align_to_wrong(self
):
240 memory_map
= MemoryMap(addr_width
=16, data_width
=8)
241 with self
.assertRaisesRegex(ValueError,
242 r
"Alignment must be a non-negative integer, not -1"):
243 memory_map
.align_to(-1)
246 class MemoryMapDiscoveryTestCase(unittest
.TestCase
):
248 self
.root
= MemoryMap(addr_width
=32, data_width
=32)
250 self
.root
.add_resource(self
.res1
, size
=16)
251 self
.win1
= MemoryMap(addr_width
=16, data_width
=32)
252 self
.root
.add_window(self
.win1
)
254 self
.win1
.add_resource(self
.res2
, size
=32)
256 self
.win1
.add_resource(self
.res3
, size
=32)
258 self
.root
.add_resource(self
.res4
, size
=1)
259 self
.win2
= MemoryMap(addr_width
=16, data_width
=8)
260 self
.root
.add_window(self
.win2
, sparse
=True)
262 self
.win2
.add_resource(self
.res5
, size
=16)
263 self
.win3
= MemoryMap(addr_width
=16, data_width
=8)
264 self
.root
.add_window(self
.win3
, sparse
=False)
266 self
.win3
.add_resource(self
.res6
, size
=16)
268 def test_iter_all_resources(self
):
269 self
.assertEqual(list(self
.root
.all_resources()), [
270 (self
.res1
, (0x00000000, 0x00000010, 32)),
271 (self
.res2
, (0x00010000, 0x00010020, 32)),
272 (self
.res3
, (0x00010020, 0x00010040, 32)),
273 (self
.res4
, (0x00020000, 0x00020001, 32)),
274 (self
.res5
, (0x00030000, 0x00030010, 8)),
275 (self
.res6
, (0x00040000, 0x00040004, 32)),
278 def test_find_resource(self
):
279 for res
, loc
in self
.root
.all_resources():
280 self
.assertEqual(self
.root
.find_resource(res
), loc
)
282 def test_find_resource_wrong(self
):
283 with self
.assertRaises(KeyError) as error
:
284 self
.root
.find_resource("resNA")
285 self
.assertEqual(error
.exception
.args
, ("resNA",))
287 def test_decode_address(self
):
288 for res
, (start
, end
, width
) in self
.root
.all_resources():
289 self
.assertEqual(self
.root
.decode_address(start
), res
)
290 self
.assertEqual(self
.root
.decode_address(end
- 1), res
)
292 def test_decode_address_missing(self
):
293 self
.assertIsNone(self
.root
.decode_address(0x00000100))