1 from ..hdl
.ast
import *
4 from ..hdl
.xfrm
import *
5 from ..hdl
.mem
import *
9 class DomainRenamerTestCase(FHDLTestCase
):
18 def test_rename_signals(self
):
21 self
.s1
.eq(ClockSignal()),
22 ResetSignal().eq(self
.s2
),
24 self
.s4
.eq(ClockSignal("other")),
25 self
.s5
.eq(ResetSignal("other")),
27 f
.add_driver(self
.s1
, None)
28 f
.add_driver(self
.s2
, None)
29 f
.add_driver(self
.s3
, "sync")
31 f
= DomainRenamer("pix")(f
)
32 self
.assertRepr(f
.statements
, """
34 (eq (sig s1) (clk pix))
35 (eq (rst pix) (sig s2))
36 (eq (sig s3) (const 1'd0))
37 (eq (sig s4) (clk other))
38 (eq (sig s5) (rst other))
41 self
.assertEqual(f
.drivers
, {
42 None: SignalSet((self
.s1
, self
.s2
)),
43 "pix": SignalSet((self
.s3
,)),
46 def test_rename_multi(self
):
49 self
.s1
.eq(ClockSignal()),
50 self
.s2
.eq(ResetSignal("other")),
53 f
= DomainRenamer({"sync": "pix", "other": "pix2"})(f
)
54 self
.assertRepr(f
.statements
, """
56 (eq (sig s1) (clk pix))
57 (eq (sig s2) (rst pix2))
61 def test_rename_cd(self
):
62 cd_sync
= ClockDomain()
63 cd_pix
= ClockDomain()
66 f
.add_domains(cd_sync
, cd_pix
)
68 f
= DomainRenamer("ext")(f
)
69 self
.assertEqual(cd_sync
.name
, "ext")
70 self
.assertEqual(f
.domains
, {
75 def test_rename_cd_subfragment(self
):
76 cd_sync
= ClockDomain()
77 cd_pix
= ClockDomain()
80 f1
.add_domains(cd_sync
, cd_pix
)
82 f2
.add_domains(cd_sync
)
83 f1
.add_subfragment(f2
)
85 f1
= DomainRenamer("ext")(f1
)
86 self
.assertEqual(cd_sync
.name
, "ext")
87 self
.assertEqual(f1
.domains
, {
92 def test_rename_wrong_to_comb(self
):
93 with self
.assertRaises(ValueError,
94 msg
="Domain 'sync' may not be renamed to 'comb'"):
97 def test_rename_wrong_from_comb(self
):
98 with self
.assertRaises(ValueError,
99 msg
="Domain 'comb' may not be renamed"):
100 DomainRenamer({"comb": "sync"})
103 class DomainLowererTestCase(FHDLTestCase
):
107 def test_lower_clk(self
):
112 self
.s
.eq(ClockSignal("sync"))
115 f
= DomainLowerer()(f
)
116 self
.assertRepr(f
.statements
, """
118 (eq (sig s) (sig clk))
122 def test_lower_rst(self
):
127 self
.s
.eq(ResetSignal("sync"))
130 f
= DomainLowerer()(f
)
131 self
.assertRepr(f
.statements
, """
133 (eq (sig s) (sig rst))
137 def test_lower_rst_reset_less(self
):
138 sync
= ClockDomain(reset_less
=True)
142 self
.s
.eq(ResetSignal("sync", allow_reset_less
=True))
145 f
= DomainLowerer()(f
)
146 self
.assertRepr(f
.statements
, """
148 (eq (sig s) (const 1'd0))
152 def test_lower_drivers(self
):
156 f
.add_domains(sync
, pix
)
157 f
.add_driver(ClockSignal("pix"), None)
158 f
.add_driver(ResetSignal("pix"), "sync")
160 f
= DomainLowerer()(f
)
161 self
.assertEqual(f
.drivers
, {
162 None: SignalSet((pix
.clk
,)),
163 "sync": SignalSet((pix
.rst
,))
166 def test_lower_wrong_domain(self
):
169 self
.s
.eq(ClockSignal("xxx"))
172 with self
.assertRaises(DomainError
,
173 msg
="Signal (clk xxx) refers to nonexistent domain 'xxx'"):
176 def test_lower_wrong_reset_less_domain(self
):
177 sync
= ClockDomain(reset_less
=True)
181 self
.s
.eq(ResetSignal("sync"))
184 with self
.assertRaises(DomainError
,
185 msg
="Signal (rst sync) refers to reset of reset-less domain 'sync'"):
189 class SampleLowererTestCase(FHDLTestCase
):
196 def test_lower_signal(self
):
199 self
.o1
.eq(Sample(self
.i
, 2, "sync")),
200 self
.o2
.eq(Sample(self
.i
, 1, "sync")),
201 self
.o3
.eq(Sample(self
.i
, 1, "pix")),
204 f
= SampleLowerer()(f
)
205 self
.assertRepr(f
.statements
, """
207 (eq (sig o1) (sig $sample$s$i$sync$2))
208 (eq (sig o2) (sig $sample$s$i$sync$1))
209 (eq (sig o3) (sig $sample$s$i$pix$1))
210 (eq (sig $sample$s$i$sync$1) (sig i))
211 (eq (sig $sample$s$i$sync$2) (sig $sample$s$i$sync$1))
212 (eq (sig $sample$s$i$pix$1) (sig i))
215 self
.assertEqual(len(f
.drivers
["sync"]), 2)
216 self
.assertEqual(len(f
.drivers
["pix"]), 1)
218 def test_lower_const(self
):
221 self
.o1
.eq(Sample(1, 2, "sync")),
224 f
= SampleLowerer()(f
)
225 self
.assertRepr(f
.statements
, """
227 (eq (sig o1) (sig $sample$c$1$sync$2))
228 (eq (sig $sample$c$1$sync$1) (const 1'd1))
229 (eq (sig $sample$c$1$sync$2) (sig $sample$c$1$sync$1))
232 self
.assertEqual(len(f
.drivers
["sync"]), 2)
235 class SwitchCleanerTestCase(FHDLTestCase
):
236 def test_clean(self
):
252 self
.assertRepr(SwitchCleaner()(stmts
), """
256 (eq (sig a) (const 1'd0)))
258 (eq (sig b) (const 1'd1)))
264 class LHSGroupAnalyzerTestCase(FHDLTestCase
):
265 def test_no_group_unrelated(self
):
273 groups
= LHSGroupAnalyzer()(stmts
)
274 self
.assertEqual(list(groups
.values()), [
279 def test_group_related(self
):
287 groups
= LHSGroupAnalyzer()(stmts
)
288 self
.assertEqual(list(groups
.values()), [
292 def test_no_loops(self
):
301 groups
= LHSGroupAnalyzer()(stmts
)
302 self
.assertEqual(list(groups
.values()), [
306 def test_switch(self
):
316 groups
= LHSGroupAnalyzer()(stmts
)
317 self
.assertEqual(list(groups
.values()), [
322 def test_lhs_empty(self
):
327 groups
= LHSGroupAnalyzer()(stmts
)
328 self
.assertEqual(list(groups
.values()), [
332 class LHSGroupFilterTestCase(FHDLTestCase
):
333 def test_filter(self
):
347 self
.assertRepr(LHSGroupFilter(SignalSet((a
,)))(stmts
), """
351 (eq (sig a) (const 1'd0)))
357 def test_lhs_empty(self
):
362 self
.assertRepr(LHSGroupFilter(SignalSet())(stmts
), "()")
365 class ResetInserterTestCase(FHDLTestCase
):
368 self
.s2
= Signal(reset
=1)
369 self
.s3
= Signal(reset
=1, reset_less
=True)
372 def test_reset_default(self
):
377 f
.add_driver(self
.s1
, "sync")
379 f
= ResetInserter(self
.c1
)(f
)
380 self
.assertRepr(f
.statements
, """
382 (eq (sig s1) (const 1'd1))
384 (case 1 (eq (sig s1) (const 1'd0)))
389 def test_reset_cd(self
):
395 f
.add_domains(ClockDomain("sync"))
396 f
.add_driver(self
.s1
, "sync")
397 f
.add_driver(self
.s2
, "pix")
399 f
= ResetInserter({"pix": self
.c1
})(f
)
400 self
.assertRepr(f
.statements
, """
402 (eq (sig s1) (const 1'd1))
403 (eq (sig s2) (const 1'd0))
405 (case 1 (eq (sig s2) (const 1'd1)))
410 def test_reset_value(self
):
415 f
.add_driver(self
.s2
, "sync")
417 f
= ResetInserter(self
.c1
)(f
)
418 self
.assertRepr(f
.statements
, """
420 (eq (sig s2) (const 1'd0))
422 (case 1 (eq (sig s2) (const 1'd1)))
427 def test_reset_less(self
):
432 f
.add_driver(self
.s3
, "sync")
434 f
= ResetInserter(self
.c1
)(f
)
435 self
.assertRepr(f
.statements
, """
437 (eq (sig s3) (const 1'd0))
445 class EnableInserterTestCase(FHDLTestCase
):
452 def test_enable_default(self
):
457 f
.add_driver(self
.s1
, "sync")
459 f
= EnableInserter(self
.c1
)(f
)
460 self
.assertRepr(f
.statements
, """
462 (eq (sig s1) (const 1'd1))
464 (case 0 (eq (sig s1) (sig s1)))
469 def test_enable_cd(self
):
475 f
.add_driver(self
.s1
, "sync")
476 f
.add_driver(self
.s2
, "pix")
478 f
= EnableInserter({"pix": self
.c1
})(f
)
479 self
.assertRepr(f
.statements
, """
481 (eq (sig s1) (const 1'd1))
482 (eq (sig s2) (const 1'd0))
484 (case 0 (eq (sig s2) (sig s2)))
489 def test_enable_subfragment(self
):
494 f1
.add_driver(self
.s1
, "sync")
500 f2
.add_driver(self
.s2
, "sync")
501 f1
.add_subfragment(f2
)
503 f1
= EnableInserter(self
.c1
)(f1
)
504 (f2
, _
), = f1
.subfragments
505 self
.assertRepr(f1
.statements
, """
507 (eq (sig s1) (const 1'd1))
509 (case 0 (eq (sig s1) (sig s1)))
513 self
.assertRepr(f2
.statements
, """
515 (eq (sig s2) (const 1'd1))
517 (case 0 (eq (sig s2) (sig s2)))
522 def test_enable_read_port(self
):
523 mem
= Memory(width
=8, depth
=4)
524 f
= EnableInserter(self
.c1
)(mem
.read_port(transparent
=False)).elaborate(platform
=None)
525 self
.assertRepr(f
.named_ports
["EN"][0], """
526 (m (sig c1) (sig mem_r_en) (const 1'd0))
529 def test_enable_write_port(self
):
530 mem
= Memory(width
=8, depth
=4)
531 f
= EnableInserter(self
.c1
)(mem
.write_port()).elaborate(platform
=None)
532 self
.assertRepr(f
.named_ports
["EN"][0], """
533 (m (sig c1) (cat (repl (slice (sig mem_w_en) 0:1) 8)) (const 8'd0))
537 class _MockElaboratable(Elaboratable
):
541 def elaborate(self
, platform
):
546 f
.add_driver(self
.s1
, "sync")
550 class TransformedElaboratableTestCase(FHDLTestCase
):
555 def test_getattr(self
):
556 e
= _MockElaboratable()
557 te
= EnableInserter(self
.c1
)(e
)
559 self
.assertIs(te
.s1
, e
.s1
)
561 def test_composition(self
):
562 e
= _MockElaboratable()
563 te1
= EnableInserter(self
.c1
)(e
)
564 te2
= ResetInserter(self
.c2
)(te1
)
566 self
.assertIsInstance(te1
, TransformedElaboratable
)
567 self
.assertIs(te1
, te2
)
569 f
= Fragment
.get(te2
, None)
570 self
.assertRepr(f
.statements
, """
572 (eq (sig s1) (const 1'd1))
574 (case 0 (eq (sig s1) (sig s1)))
577 (case 1 (eq (sig s1) (const 1'd0)))
583 class MockUserValue(UserValue
):
584 def __init__(self
, lowered
):
586 self
.lowered
= lowered
592 class UserValueTestCase(FHDLTestCase
):
596 self
.uv
= MockUserValue(self
.s
)
598 def test_lower(self
):
605 for signal
in self
.uv
._lhs
_signals
():
606 f
.add_driver(signal
, "sync")
608 f
= ResetInserter(self
.c
)(f
)
609 f
= DomainLowerer()(f
)
610 self
.assertRepr(f
.statements
, """
612 (eq (sig s) (const 1'd1))
614 (case 1 (eq (sig s) (const 1'd0)))
617 (case 1 (eq (sig s) (const 1'd0)))