Mention contrib/test_failfast in test README
[gram.git] / gram / test / test_compat.py
1 #nmigen: UnusedElaboratable=no
2 from nmigen import *
3 from nmigen.hdl.ast import Past
4 from nmigen.asserts import Assert, Assume
5
6 from gram.compat import *
7 from utils import *
8
9 class DelayedEnterTestCase(FHDLTestCase):
10 def test_sequence(self):
11 def sequence(expected_delay):
12 m = Module()
13
14 before = Signal()
15 end = Signal()
16
17 with m.FSM():
18 with m.State("Before-Delayed-Enter"):
19 m.d.comb += before.eq(1)
20 m.next = "Delayed-Enter"
21
22 delayed_enter(m, "Delayed-Enter", "End-Delayed-Enter", expected_delay)
23
24 with m.State("End-Delayed-Enter"):
25 m.d.comb += end.eq(1)
26
27 def process():
28 while (yield before):
29 yield
30
31 delay = 0
32 while not (yield end):
33 yield
34 delay += 1
35
36 self.assertEqual(delay, expected_delay)
37
38 runSimulation(m, process, "test_delayedenter.vcd")
39
40 with self.assertRaises(AssertionError):
41 sequence(0)
42 sequence(1)
43 sequence(2)
44 sequence(10)
45 sequence(100)
46 sequence(1000)
47
48 class TimelineTestCase(FHDLTestCase):
49 def test_sequence(self):
50 sigA = Signal()
51 sigB = Signal()
52 sigC = Signal()
53 timeline = Timeline([
54 (1, sigA.eq(1)),
55 (5, sigA.eq(1)),
56 (7, sigA.eq(0)),
57 (10, sigB.eq(1)),
58 (11, sigB.eq(0)),
59 ])
60
61 def process():
62 # Test default value for unset signals
63 self.assertFalse((yield sigA))
64 self.assertFalse((yield sigB))
65
66 # Ensure that the sequence isn't triggered without the trigger signal
67 for i in range(100):
68 yield
69 self.assertFalse((yield sigA))
70 self.assertFalse((yield sigB))
71
72 yield timeline.trigger.eq(1)
73 yield
74 yield timeline.trigger.eq(0)
75
76 for i in range(11+1):
77 yield
78
79 if i == 1:
80 self.assertTrue((yield sigA))
81 self.assertFalse((yield sigB))
82 elif i == 5:
83 self.assertTrue((yield sigA))
84 self.assertFalse((yield sigB))
85 elif i == 7:
86 self.assertFalse((yield sigA))
87 self.assertFalse((yield sigB))
88 elif i == 10:
89 self.assertFalse((yield sigA))
90 self.assertTrue((yield sigB))
91 elif i == 11:
92 self.assertFalse((yield sigA))
93 self.assertFalse((yield sigB))
94
95 # Ensure no changes happen once the sequence is done
96 for i in range(100):
97 yield
98 self.assertFalse((yield sigA))
99 self.assertFalse((yield sigB))
100
101 runSimulation(timeline, process, "test_timeline.vcd")
102
103 class RoundRobinOutputMatchSpec(Elaboratable):
104 def __init__(self, dut):
105 self.dut = dut
106
107 def elaborate(self, platform):
108 m = Module()
109
110 m.d.comb += Assume(Rose(self.dut.stb).implies(self.dut.request == Past(self.dut.request)))
111
112 m.d.sync += Assert(((Past(self.dut.request) != 0) & Past(self.dut.stb)).implies(Past(self.dut.request) & (1 << self.dut.grant)))
113
114 return m
115
116 class RoundRobinTestCase(FHDLTestCase):
117 def test_sequence(self):
118 m = Module()
119 m.submodules.rb = roundrobin = RoundRobin(8)
120
121 def process():
122 yield roundrobin.request.eq(0b10001000)
123 yield roundrobin.stb.eq(1)
124 yield
125 yield
126
127 self.assertEqual((yield roundrobin.grant), 3)
128 yield
129
130 self.assertEqual((yield roundrobin.grant), 7)
131 yield
132
133 self.assertEqual((yield roundrobin.grant), 3)
134 yield roundrobin.request.eq(0b00000001)
135 yield
136 yield
137
138 self.assertEqual((yield roundrobin.grant), 0)
139
140 runSimulation(m, process, "test_roundrobin.vcd")
141
142 # def test_output_match(self):
143 # roundrobin = RoundRobin(32)
144 # spec = RoundRobinOutputMatchSpec(roundrobin)
145 # self.assertFormal(spec, mode="bmc", depth=10)