1 from collections
import OrderedDict
3 from ..hdl
.ast
import *
5 from ..hdl
.dsl
import *
9 class DSLTestCase(FHDLTestCase
):
19 def test_d_comb(self
):
21 m
.d
.comb
+= self
.c1
.eq(1)
23 self
.assertEqual(m
._driving
[self
.c1
], None)
24 self
.assertRepr(m
._statements
, """(
25 (eq (sig c1) (const 1'd1))
28 def test_d_sync(self
):
30 m
.d
.sync
+= self
.c1
.eq(1)
32 self
.assertEqual(m
._driving
[self
.c1
], "sync")
33 self
.assertRepr(m
._statements
, """(
34 (eq (sig c1) (const 1'd1))
39 m
.d
.pix
+= self
.c1
.eq(1)
41 self
.assertEqual(m
._driving
[self
.c1
], "pix")
42 self
.assertRepr(m
._statements
, """(
43 (eq (sig c1) (const 1'd1))
46 def test_d_index(self
):
48 m
.d
["pix"] += self
.c1
.eq(1)
50 self
.assertEqual(m
._driving
[self
.c1
], "pix")
51 self
.assertRepr(m
._statements
, """(
52 (eq (sig c1) (const 1'd1))
55 def test_d_no_conflict(self
):
57 m
.d
.comb
+= self
.w1
[0].eq(1)
58 m
.d
.comb
+= self
.w1
[1].eq(1)
60 def test_d_conflict(self
):
62 with self
.assertRaises(SyntaxError,
63 msg
="Driver-driver conflict: trying to drive (sig c1) from d.sync, but it "
64 "is already driven from d.comb"):
65 m
.d
.comb
+= self
.c1
.eq(1)
66 m
.d
.sync
+= self
.c1
.eq(1)
68 def test_d_wrong(self
):
70 with self
.assertRaises(AttributeError,
71 msg
="Cannot assign 'd.pix' attribute; did you mean 'd.pix +='?"):
74 def test_d_asgn_wrong(self
):
76 with self
.assertRaises(SyntaxError,
77 msg
="Only assignments may be appended to d.sync"):
78 m
.d
.sync
+= Switch(self
.s1
, {})
80 def test_comb_wrong(self
):
82 with self
.assertRaises(AttributeError,
83 msg
="'Module' object has no attribute 'comb'; did you mean 'd.comb'?"):
84 m
.comb
+= self
.c1
.eq(1)
86 def test_sync_wrong(self
):
88 with self
.assertRaises(AttributeError,
89 msg
="'Module' object has no attribute 'sync'; did you mean 'd.sync'?"):
90 m
.sync
+= self
.c1
.eq(1)
92 def test_attr_wrong(self
):
94 with self
.assertRaises(AttributeError,
95 msg
="'Module' object has no attribute 'nonexistentattr'"):
101 m
.d
.comb
+= self
.c1
.eq(1)
103 self
.assertRepr(m
._statements
, """
105 (switch (cat (sig s1))
106 (case 1 (eq (sig c1) (const 1'd1)))
111 def test_If_Elif(self
):
114 m
.d
.comb
+= self
.c1
.eq(1)
115 with m
.Elif(self
.s2
):
116 m
.d
.sync
+= self
.c2
.eq(0)
118 self
.assertRepr(m
._statements
, """
120 (switch (cat (sig s1) (sig s2))
121 (case -1 (eq (sig c1) (const 1'd1)))
122 (case 1- (eq (sig c2) (const 1'd0)))
127 def test_If_Elif_Else(self
):
130 m
.d
.comb
+= self
.c1
.eq(1)
131 with m
.Elif(self
.s2
):
132 m
.d
.sync
+= self
.c2
.eq(0)
134 m
.d
.comb
+= self
.c3
.eq(1)
136 self
.assertRepr(m
._statements
, """
138 (switch (cat (sig s1) (sig s2))
139 (case -1 (eq (sig c1) (const 1'd1)))
140 (case 1- (eq (sig c2) (const 1'd0)))
141 (case -- (eq (sig c3) (const 1'd1)))
146 def test_If_If(self
):
149 m
.d
.comb
+= self
.c1
.eq(1)
151 m
.d
.comb
+= self
.c2
.eq(1)
153 self
.assertRepr(m
._statements
, """
155 (switch (cat (sig s1))
156 (case 1 (eq (sig c1) (const 1'd1)))
158 (switch (cat (sig s2))
159 (case 1 (eq (sig c2) (const 1'd1)))
164 def test_If_nested_If(self
):
167 m
.d
.comb
+= self
.c1
.eq(1)
169 m
.d
.comb
+= self
.c2
.eq(1)
171 self
.assertRepr(m
._statements
, """
173 (switch (cat (sig s1))
174 (case 1 (eq (sig c1) (const 1'd1))
175 (switch (cat (sig s2))
176 (case 1 (eq (sig c2) (const 1'd1)))
183 def test_If_dangling_Else(self
):
186 m
.d
.comb
+= self
.c1
.eq(1)
188 m
.d
.comb
+= self
.c2
.eq(1)
190 m
.d
.comb
+= self
.c3
.eq(1)
192 self
.assertRepr(m
._statements
, """
194 (switch (cat (sig s1))
196 (eq (sig c1) (const 1'd1))
197 (switch (cat (sig s2))
198 (case 1 (eq (sig c2) (const 1'd1)))
202 (eq (sig c3) (const 1'd1))
208 def test_Elif_wrong(self
):
210 with self
.assertRaises(SyntaxError,
211 msg
="Elif without preceding If"):
212 with m
.Elif(self
.s2
):
215 def test_Else_wrong(self
):
217 with self
.assertRaises(SyntaxError,
218 msg
="Else without preceding If/Elif"):
222 def test_If_wide(self
):
225 m
.d
.comb
+= self
.c1
.eq(1)
227 self
.assertRepr(m
._statements
, """
229 (switch (cat (b (sig w1)))
230 (case 1 (eq (sig c1) (const 1'd1)))
235 def test_Switch(self
):
237 with m
.Switch(self
.w1
):
239 m
.d
.comb
+= self
.c1
.eq(1)
241 m
.d
.comb
+= self
.c2
.eq(1)
243 self
.assertRepr(m
._statements
, """
246 (case 0011 (eq (sig c1) (const 1'd1)))
247 (case 11-- (eq (sig c2) (const 1'd1)))
252 def test_Switch_default(self
):
254 with m
.Switch(self
.w1
):
256 m
.d
.comb
+= self
.c1
.eq(1)
258 m
.d
.comb
+= self
.c2
.eq(1)
260 self
.assertRepr(m
._statements
, """
263 (case 0011 (eq (sig c1) (const 1'd1)))
264 (case ---- (eq (sig c2) (const 1'd1)))
269 def test_Switch_const_test(self
):
273 m
.d
.comb
+= self
.c1
.eq(1)
275 self
.assertRepr(m
._statements
, """
278 (case 1 (eq (sig c1) (const 1'd1)))
283 def test_Case_width_wrong(self
):
285 with m
.Switch(self
.w1
):
286 with self
.assertRaises(SyntaxError,
287 msg
="Case value '--' must have the same width as test (which is 4)"):
291 def test_Case_outside_Switch_wrong(self
):
293 with self
.assertRaises(SyntaxError,
294 msg
="Case is not permitted outside of Switch"):
298 def test_If_inside_Switch_wrong(self
):
300 with m
.Switch(self
.s1
):
301 with self
.assertRaises(SyntaxError,
302 msg
="If is not permitted inside of Switch"):
306 def test_FSM_basic(self
):
312 with m
.State("FIRST"):
315 with m
.State("SECOND"):
320 self
.assertRepr(m
._statements
, """
322 (switch (sig fsm_state)
324 (eq (sig a) (const 1'd1))
325 (eq (sig fsm_state) (const 1'd1))
328 (eq (sig b) (~ (sig b)))
329 (switch (cat (sig c))
331 (eq (sig fsm_state) (const 1'd0)))
337 self
.assertEqual({repr(k
): v
for k
, v
in m
._driving
.items()}, {
339 "(sig fsm_state)": "sync",
343 frag
= m
.lower(platform
=None)
344 fsm
= frag
.find_generated("fsm")
345 self
.assertIsInstance(fsm
.state
, Signal
)
346 self
.assertEqual(fsm
.encoding
, OrderedDict({
350 self
.assertEqual(fsm
.decoding
, OrderedDict({
355 def test_FSM_reset(self
):
358 with m
.FSM(reset
="SECOND"):
359 with m
.State("FIRST"):
362 with m
.State("SECOND"):
365 self
.assertRepr(m
._statements
, """
367 (switch (sig fsm_state)
369 (eq (sig a) (const 1'd0))
370 (eq (sig fsm_state) (const 1'd0))
373 (eq (sig fsm_state) (const 1'd1))
379 def test_FSM_wrong_redefined(self
):
384 with self
.assertRaises(SyntaxError,
385 msg
="FSM state 'FOO' is already defined"):
389 def test_FSM_wrong_next(self
):
391 with self
.assertRaises(SyntaxError,
392 msg
="Only assignment to `m.next` is permitted"):
394 with self
.assertRaises(SyntaxError,
395 msg
="`m.next = <...>` is only permitted inside an FSM state"):
397 with self
.assertRaises(SyntaxError,
398 msg
="`m.next = <...>` is only permitted inside an FSM state"):
402 def test_auto_pop_ctrl(self
):
405 m
.d
.comb
+= self
.c1
.eq(1)
406 m
.d
.comb
+= self
.c2
.eq(1)
407 self
.assertRepr(m
._statements
, """
409 (switch (cat (b (sig w1)))
410 (case 1 (eq (sig c1) (const 1'd1)))
412 (eq (sig c2) (const 1'd1))
416 def test_submodule_anon(self
):
420 self
.assertEqual(m1
._submodules
, [(m2
, None)])
422 def test_submodule_anon_multi(self
):
426 m1
.submodules
+= m2
, m3
427 self
.assertEqual(m1
._submodules
, [(m2
, None), (m3
, None)])
429 def test_submodule_named(self
):
432 m1
.submodules
.foo
= m2
433 self
.assertEqual(m1
._submodules
, [(m2
, "foo")])
435 def test_submodule_wrong(self
):
437 with self
.assertRaises(TypeError,
438 msg
="Trying to add '1', which does not implement .get_fragment(), as a submodule"):
440 with self
.assertRaises(TypeError,
441 msg
="Trying to add '1', which does not implement .get_fragment(), as a submodule"):
444 def test_domain_named_implicit(self
):
446 m
.domains
+= ClockDomain("sync")
447 self
.assertEqual(len(m
._domains
), 1)
449 def test_domain_named_explicit(self
):
451 m
.domains
.foo
= ClockDomain()
452 self
.assertEqual(len(m
._domains
), 1)
453 self
.assertEqual(m
._domains
[0].name
, "foo")
455 def test_lower(self
):
457 m1
.d
.comb
+= self
.c1
.eq(self
.s1
)
459 m2
.d
.comb
+= self
.c2
.eq(self
.s2
)
460 m2
.d
.sync
+= self
.c3
.eq(self
.s3
)
461 m1
.submodules
.foo
= m2
463 f1
= m1
.lower(platform
=None)
464 self
.assertRepr(f1
.statements
, """
466 (eq (sig c1) (sig s1))
469 self
.assertEqual(f1
.drivers
, {
470 None: SignalSet((self
.c1
,))
472 self
.assertEqual(len(f1
.subfragments
), 1)
473 (f2
, f2_name
), = f1
.subfragments
474 self
.assertEqual(f2_name
, "foo")
475 self
.assertRepr(f2
.statements
, """
477 (eq (sig c2) (sig s2))
478 (eq (sig c3) (sig s3))
481 self
.assertEqual(f2
.drivers
, {
482 None: SignalSet((self
.c2
,)),
483 "sync": SignalSet((self
.c3
,))
485 self
.assertEqual(len(f2
.subfragments
), 0)