1 from ..hdl
.ast
import *
7 class FragmentDriversTestCase(FHDLTestCase
):
10 self
.assertEqual(list(f
.iter_comb()), [])
11 self
.assertEqual(list(f
.iter_sync()), [])
14 class FragmentPortsTestCase(FHDLTestCase
):
25 self
.assertEqual(list(f
.iter_ports()), [])
27 f
._propagate
_ports
(ports
=())
28 self
.assertEqual(f
.ports
, ValueDict([]))
30 def test_iter_signals(self
):
32 f
.add_ports(self
.s1
, self
.s2
, kind
="io")
33 self
.assertEqual(ValueSet((self
.s1
, self
.s2
)), f
.iter_signals())
35 def test_self_contained(self
):
42 f
._propagate
_ports
(ports
=())
43 self
.assertEqual(f
.ports
, ValueDict([]))
45 def test_infer_input(self
):
51 f
._propagate
_ports
(ports
=())
52 self
.assertEqual(f
.ports
, ValueDict([
56 def test_request_output(self
):
62 f
._propagate
_ports
(ports
=(self
.c1
,))
63 self
.assertEqual(f
.ports
, ValueDict([
68 def test_input_in_subfragment(self
):
77 f1
.add_subfragment(f2
)
78 f1
._propagate_ports(ports
=())
79 self
.assertEqual(f1
.ports
, ValueDict())
80 self
.assertEqual(f2
.ports
, ValueDict([
84 def test_input_only_in_subfragment(self
):
90 f1
.add_subfragment(f2
)
91 f1
._propagate_ports(ports
=())
92 self
.assertEqual(f1
.ports
, ValueDict([
95 self
.assertEqual(f2
.ports
, ValueDict([
99 def test_output_from_subfragment(self
):
108 f1
.add_subfragment(f2
)
110 f1
._propagate_ports(ports
=(self
.c2
,))
111 self
.assertEqual(f1
.ports
, ValueDict([
114 self
.assertEqual(f2
.ports
, ValueDict([
118 def test_input_cd(self
):
125 f
.add_driver(self
.c1
, "sync")
127 f
._propagate
_ports
(ports
=())
128 self
.assertEqual(f
.ports
, ValueDict([
134 def test_input_cd_reset_less(self
):
135 sync
= ClockDomain(reset_less
=True)
141 f
.add_driver(self
.c1
, "sync")
143 f
._propagate
_ports
(ports
=())
144 self
.assertEqual(f
.ports
, ValueDict([
150 class FragmentDomainsTestCase(FHDLTestCase
):
151 def test_iter_signals(self
):
153 cd2
= ClockDomain(reset_less
=True)
158 f
.add_domains(cd1
, cd2
)
159 f
.add_driver(s1
, "cd1")
160 self
.assertEqual(ValueSet((cd1
.clk
, cd1
.rst
, s1
)), f
.iter_signals())
161 f
.add_driver(s2
, "cd2")
162 self
.assertEqual(ValueSet((cd1
.clk
, cd1
.rst
, cd2
.clk
, s1
, s2
)), f
.iter_signals())
164 def test_propagate_up(self
):
169 f1
.add_subfragment(f2
)
172 f1
._propagate_domains_up()
173 self
.assertEqual(f1
.domains
, {"cd": cd
})
175 def test_domain_conflict(self
):
176 cda
= ClockDomain("sync")
177 cdb
= ClockDomain("sync")
184 f
.add_subfragment(fa
, "a")
185 f
.add_subfragment(fb
, "b")
187 f
._propagate
_domains
_up
()
188 self
.assertEqual(f
.domains
, {"a_sync": cda
, "b_sync": cdb
})
189 (fa
, _
), (fb
, _
) = f
.subfragments
190 self
.assertEqual(fa
.domains
, {"a_sync": cda
})
191 self
.assertEqual(fb
.domains
, {"b_sync": cdb
})
193 def test_domain_conflict_anon(self
):
194 cda
= ClockDomain("sync")
195 cdb
= ClockDomain("sync")
202 f
.add_subfragment(fa
, "a")
203 f
.add_subfragment(fb
)
205 with self
.assertRaises(DomainError
,
206 msg
="Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
207 "'top'; it is necessary to either rename subfragment domains explicitly, "
208 "or give names to subfragments"):
209 f
._propagate
_domains
_up
()
211 def test_domain_conflict_name(self
):
212 cda
= ClockDomain("sync")
213 cdb
= ClockDomain("sync")
220 f
.add_subfragment(fa
, "x")
221 f
.add_subfragment(fb
, "x")
223 with self
.assertRaises(DomainError
,
224 msg
="Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
225 "of which have identical names; it is necessary to either rename subfragment "
226 "domains explicitly, or give distinct names to subfragments"):
227 f
._propagate
_domains
_up
()
229 def test_propagate_down(self
):
235 f1
.add_subfragment(f2
)
237 f1
._propagate_domains_down()
238 self
.assertEqual(f2
.domains
, {"cd": cd
})
240 def test_propagate_down_idempotent(self
):
247 f1
.add_subfragment(f2
)
249 f1
._propagate_domains_down()
250 self
.assertEqual(f1
.domains
, {"cd": cd
})
251 self
.assertEqual(f2
.domains
, {"cd": cd
})
253 def test_propagate(self
):
259 f1
.add_subfragment(f2
)
261 f1
._propagate_domains(ensure_sync_exists
=False)
262 self
.assertEqual(f1
.domains
, {"cd": cd
})
263 self
.assertEqual(f2
.domains
, {"cd": cd
})
265 def test_propagate_ensure_sync(self
):
268 f1
.add_subfragment(f2
)
270 f1
._propagate_domains(ensure_sync_exists
=True)
271 self
.assertEqual(f1
.domains
.keys(), {"sync"})
272 self
.assertEqual(f2
.domains
.keys(), {"sync"})
273 self
.assertEqual(f1
.domains
["sync"], f2
.domains
["sync"])
276 class FragmentDriverConflictTestCase(FHDLTestCase
):
277 def setUp_self_sub(self
):
283 self
.f1
.add_statements(self
.c1
.eq(0))
284 self
.f1
.add_driver(self
.s1
)
285 self
.f1
.add_driver(self
.c1
, "sync")
287 self
.f1a
= Fragment()
288 self
.f1
.add_subfragment(self
.f1a
, "f1a")
291 self
.f2
.add_statements(self
.c2
.eq(1))
292 self
.f2
.add_driver(self
.s1
)
293 self
.f2
.add_driver(self
.c2
, "sync")
294 self
.f1
.add_subfragment(self
.f2
)
296 self
.f1b
= Fragment()
297 self
.f1
.add_subfragment(self
.f1b
, "f1b")
299 self
.f2a
= Fragment()
300 self
.f2
.add_subfragment(self
.f2a
, "f2a")
302 def test_conflict_self_sub(self
):
303 self
.setUp_self_sub()
305 self
.f1
._resolve_driver_conflicts(mode
="silent")
306 self
.assertEqual(self
.f1
.subfragments
, [
311 self
.assertRepr(self
.f1
.statements
, """
313 (eq (sig c1) (const 1'd0))
314 (eq (sig c2) (const 1'd1))
317 self
.assertEqual(self
.f1
.drivers
, {
318 None: ValueSet((self
.s1
,)),
319 "sync": ValueSet((self
.c1
, self
.c2
)),
322 def test_conflict_self_sub_error(self
):
323 self
.setUp_self_sub()
325 with self
.assertRaises(DriverConflict
,
326 msg
="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>"):
327 self
.f1
._resolve_driver_conflicts(mode
="error")
329 def test_conflict_self_sub_warning(self
):
330 self
.setUp_self_sub()
332 with self
.assertWarns(DriverConflict
,
333 msg
="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>; "
334 "hierarchy will be flattened"):
335 self
.f1
._resolve_driver_conflicts(mode
="warn")
337 def setUp_sub_sub(self
):
345 self
.f2
.add_driver(self
.s1
)
346 self
.f2
.add_statements(self
.c1
.eq(0))
347 self
.f1
.add_subfragment(self
.f2
)
350 self
.f3
.add_driver(self
.s1
)
351 self
.f3
.add_statements(self
.c2
.eq(1))
352 self
.f1
.add_subfragment(self
.f3
)
354 def test_conflict_sub_sub(self
):
357 self
.f1
._resolve_driver_conflicts(mode
="silent")
358 self
.assertEqual(self
.f1
.subfragments
, [])
359 self
.assertRepr(self
.f1
.statements
, """
361 (eq (sig c1) (const 1'd0))
362 (eq (sig c2) (const 1'd1))
366 def setUp_self_subsub(self
):
372 self
.f1
.add_driver(self
.s1
)
375 self
.f2
.add_statements(self
.c1
.eq(0))
376 self
.f1
.add_subfragment(self
.f2
)
379 self
.f3
.add_driver(self
.s1
)
380 self
.f3
.add_statements(self
.c2
.eq(1))
381 self
.f2
.add_subfragment(self
.f3
)
383 def test_conflict_self_subsub(self
):
384 self
.setUp_self_subsub()
386 self
.f1
._resolve_driver_conflicts(mode
="silent")
387 self
.assertEqual(self
.f1
.subfragments
, [])
388 self
.assertRepr(self
.f1
.statements
, """
390 (eq (sig c1) (const 1'd0))
391 (eq (sig c2) (const 1'd1))