switch to exact version of cython
[ieee754fpu.git] / src / ieee754 / cordic / sin_cos_pipe_stage.py
1 from nmigen import Module, Signal
2 from nmutil.pipemodbase import PipeModBase
3 from ieee754.cordic.pipe_data import CordicData, CordicInitialData
4 import math
5 import bigfloat as bf
6 from bigfloat import BigFloat
7
8
9 class CordicInitialStage(PipeModBase):
10 def __init__(self, pspec):
11 super().__init__(pspec, "cordicinit")
12
13 def ispec(self):
14 return CordicInitialData(self.pspec)
15
16 def ospec(self):
17 return CordicData(self.pspec)
18
19 def elaborate(self, platform):
20 m = Module()
21 comb = m.d.comb
22
23 An = 1.0
24 for i in range(self.pspec.iterations):
25 An *= math.sqrt(1 + 2**(-2*i))
26 X0 = int(round(self.pspec.M*1/An))
27
28 comb += self.o.x.eq(X0)
29 comb += self.o.y.eq(0)
30 comb += self.o.z.eq(self.i.z0)
31
32 comb += self.o.ctx.eq(self.i.ctx)
33 return m
34
35
36 class CordicStage(PipeModBase):
37 def __init__(self, pspec, stagenum):
38 super().__init__(pspec, "cordicstage%d" % stagenum)
39 self.stagenum = stagenum
40
41 def ispec(self):
42 return CordicData(self.pspec)
43
44 def ospec(self):
45 return CordicData(self.pspec)
46
47 def elaborate(self, platform):
48 m = Module()
49 comb = m.d.comb
50
51 dx = Signal(self.i.x.shape())
52 dy = Signal(self.i.y.shape())
53 dz = Signal(self.i.z.shape())
54 with bf.quadruple_precision:
55 x = bf.atan(BigFloat(2) ** BigFloat(-self.stagenum))
56 x = x/(bf.const_pi()/2)
57 x = x * self.pspec.M
58 angle = int(round(x))
59
60 comb += dx.eq(self.i.y >> self.stagenum)
61 comb += dy.eq(self.i.x >> self.stagenum)
62 comb += dz.eq(angle)
63
64 with m.If(self.i.z >= 0):
65 comb += self.o.x.eq(self.i.x - dx)
66 comb += self.o.y.eq(self.i.y + dy)
67 comb += self.o.z.eq(self.i.z - dz)
68 with m.Else():
69 comb += self.o.x.eq(self.i.x + dx)
70 comb += self.o.y.eq(self.i.y - dy)
71 comb += self.o.z.eq(self.i.z + dz)
72
73
74 comb += self.o.ctx.eq(self.i.ctx)
75 return m