Working (ish) fpsin iterative cordic
[ieee754fpu.git] / src / ieee754 / cordic / test / test_fpsin_cos.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay
3 from nmigen.test.utils import FHDLTestCase
4
5 from ieee754.cordic.fpsin_cos import CORDIC
6 from ieee754.fpcommon.fpbase import FPNumBaseRecord
7 from python_sin_cos import run_cordic
8 from sfpy import Float16, Float32
9 import unittest
10 import math
11 import random
12
13
14 class SinCosTestCase(FHDLTestCase):
15 def run_test(self, zin=0, fracbits=8, expected_sin=0, expected_cos=0):
16
17 m = Module()
18
19 m.submodules.dut = dut = CORDIC(16)
20 z = Signal(dut.z0.width)
21 start = Signal()
22
23 sin = Signal(dut.sin.shape())
24 cos = Signal(dut.cos.shape())
25 ready = Signal()
26
27 m.d.comb += [
28 dut.z0.eq(z),
29 dut.start.eq(start),
30 sin.eq(dut.sin),
31 cos.eq(dut.cos),
32 ready.eq(dut.ready)]
33
34 sim = Simulator(m)
35 sim.add_clock(1e-6)
36
37 def process():
38 asserted = False
39 yield z.eq(zin.get_bits())
40 yield start.eq(1)
41
42 yield
43 yield start.eq(0)
44 yield
45 for i in range(fracbits * 3):
46 rdy = yield ready
47 zo = yield dut.z_out
48 if rdy and not asserted:
49 frac = self.get_frac(zo, dut.z_out.width - 2)
50 print(f"{zo:x} {frac}")
51 self.assertEqual(str(frac), zin.__str__())
52 asserted = True
53
54 real_sin = yield dut.sin
55 real_sin = self.get_frac(real_sin, dut.sin.width - 2)
56 diff = abs(real_sin - expected_sin)
57 print(f"{real_sin} {expected_sin} {diff}")
58 self.assertTrue(diff < 0.001)
59
60 yield
61
62 sim.add_sync_process(process)
63 with sim.write_vcd("fpsin_cos.vcd", "fpsin_cos.gtkw", traces=[
64 cos, sin, ready, start]):
65 sim.run()
66
67 def run_test_assert(self, z, fracbits=8):
68 zpi = z * Float16(math.pi/2)
69 e_sin = math.sin(zpi)
70 e_cos = math.cos(zpi)
71 self.run_test(zin=z, fracbits=fracbits, expected_sin=e_sin,
72 expected_cos=e_cos)
73
74 def test_1(self):
75 x = Float16(1.0)
76 print(x)
77 self.run_test_assert(x)
78
79 def test_pi_4(self):
80 x = Float16(1/3)
81 print(x)
82 self.run_test_assert(x)
83
84 def test_rand(self):
85 for i in range(500):
86 z = random.uniform(-1, 1)
87 f = Float16(z)
88 self.run_test_assert(f)
89
90 def get_frac(self, value, bits):
91 return value/(1 << bits)
92
93 if __name__ == "__main__":
94 unittest.main()