format code
[ieee754fpu.git] / src / ieee754 / cordic / test / test_fp_pipe.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Passive
3 from nmutil.formaltest import FHDLTestCase
4 from nmigen.cli import rtlil
5 from sfpy import Float32
6
7 from ieee754.cordic.fp_pipeline import FPCordicBasePipe
8 from ieee754.cordic.fp_pipe_data import FPCordicPipeSpec
9 import unittest
10 import math
11 import random
12
13
14 class SinCosTestCase(FHDLTestCase):
15 def run_test(self, inputs, outputs=iter([])):
16 m = Module()
17 pspec = FPCordicPipeSpec(width=32, rounds_per_stage=4, num_rows=1)
18 m.submodules.dut = dut = FPCordicBasePipe(pspec)
19
20 # write out module (useful for seeing what's going on)
21 # XXX WHOOPS can't do this at the moment, need to track down
22 # an issue in the ports
23 vl = rtlil.convert(dut, ports=dut.ports())
24 with open("test_cordic_pipe_sin_cos.il", "w") as f:
25 f.write(vl)
26
27 z = Signal(dut.p.data_i.a.shape())
28 z_valid = Signal()
29 ready = Signal()
30
31 m.d.comb += [
32 dut.p.data_i.a.eq(z),
33 dut.p.valid_i.eq(z_valid),
34 dut.n.ready_i.eq(ready),
35 ]
36
37 sim = Simulator(m)
38 sim.add_clock(1e-6)
39
40 def writer_process():
41 for val in inputs:
42 yield z.eq(val.bits)
43 yield z_valid.eq(1)
44 yield ready.eq(1)
45 yield
46 for i in range(40):
47 yield
48
49 def reader_process():
50 counter = 200
51 while True:
52 counter -= 1
53 if counter == 0: # some indication of progress
54 print(".", sep="", end="", flush=True)
55 counter = 200
56 yield
57 vld = yield dut.n.valid_o
58 if vld:
59 try:
60 sin, cos = outputs.__next__()
61 result = yield dut.n.data_o.x
62 result = Float32(result)
63 msg = f"cos: expected {cos} got {result}"
64 self.assertLess(abs(result - Float32(cos)),
65 Float32(2e-7), msg=msg)
66 result = yield dut.n.data_o.y
67 result = Float32(result)
68 msg = f"sin: expected {sin} got {result}"
69 self.assertLess(abs(result - Float32(sin)),
70 Float32(2e-7), msg=msg)
71 except StopIteration:
72 break
73
74 print() # newline after end of progress-indicator
75
76 sim.add_sync_process(writer_process)
77 sim.add_sync_process(reader_process)
78 with sim.write_vcd("fp_pipeline.vcd", "fp_pipeline.gtkw", traces=[
79 z]):
80 sim.run()
81
82 def test_rand(self):
83 inputs = []
84 for i in range(20000):
85 x = random.uniform(-1, 1)
86 inputs.append(Float32(x))
87 sines = [math.sin(x * Float32(math.pi/2)) for x in inputs]
88 cosines = [math.cos(x * Float32(math.pi/2)) for x in inputs]
89 outputs = zip(sines, cosines)
90 self.run_test(iter(inputs), outputs=iter(outputs))
91
92 def test_pi_2(self):
93 inputs = [Float32(0.5), Float32(1/3), Float32(2/3),
94 Float32(-.5), Float32(0.001)]
95 sines = [math.sin(x * Float32(math.pi/2)) for x in inputs]
96 cosines = [math.cos(x * Float32(math.pi/2)) for x in inputs]
97 outputs = zip(sines, cosines)
98 self.run_test(iter(inputs), outputs=iter(outputs))
99
100
101 if __name__ == "__main__":
102 unittest.main()