genlib: remove cordic (will live in pdq2)
authorSebastien Bourdeauducq <sb@m-labs.hk>
Wed, 8 Apr 2015 03:35:53 +0000 (11:35 +0800)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Wed, 8 Apr 2015 03:35:53 +0000 (11:35 +0800)
migen/genlib/cordic.py [deleted file]

diff --git a/migen/genlib/cordic.py b/migen/genlib/cordic.py
deleted file mode 100644 (file)
index 6c430da..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-from math import atan, atanh, log, sqrt, pi
-
-from migen.fhdl.std import *
-
-class TwoQuadrantCordic(Module):
-       """Coordinate rotation digital computer
-
-       Trigonometric, and arithmetic functions implemented using
-       additions/subtractions and shifts.
-
-       http://eprints.soton.ac.uk/267873/1/tcas1_cordic_review.pdf
-
-       http://www.andraka.com/files/crdcsrvy.pdf
-
-       http://zatto.free.fr/manual/Volder_CORDIC.pdf
-
-       The way the CORDIC is executed is controlled by `eval_mode`.
-       If `"iterative"` the stages are iteratively evaluated, one per clock
-       cycle. This mode uses the least amount of registers, but has the
-       lowest throughput and highest latency.  If `"pipelined"` all stages
-       are executed in every clock cycle but separated by registers.  This
-       mode has full throughput but uses many registers and has large
-       latency. If `"combinatorial"`, there are no registers, throughput is
-       maximal and latency is zero. `"pipelined"` and `"combinatorial"` use
-       the same number of shifters and adders.
-
-       The type of trigonometric/arithmetic function is determined by
-       `cordic_mode` and `func_mode`. :math:`g` is the gain of the CORDIC.
-
-               * rotate-circular: rotate the vector `(xi, yi)` by an angle `zi`.
-                 Used to calculate trigonometric functions, `sin(), cos(),
-                 tan() = sin()/cos()`, or to perform polar-to-cartesian coordinate
-                 transformation:
-
-                       .. math::
-                               x_o = g \\cos(z_i) x_i - g \\sin(z_i) y_i
-
-                               y_o = g \\sin(z_i) x_i + g \\cos(z_i) y_i
-
-               * vector-circular: determine length and angle of the vector
-                 `(xi, yi)`.  Used to calculate `arctan(), sqrt()` or
-                 to perform cartesian-to-polar transformation:
-
-                       .. math::
-                               x_o = g\\sqrt{x_i^2 + y_i^2}
-
-                               z_o = z_i + \\tan^{-1}(y_i/x_i)
-
-               * rotate-hyperbolic: hyperbolic functions of `zi`. Used to
-                 calculate hyperbolic functions, `sinh, cosh, tanh = cosh/sinh,
-                 exp = cosh + sinh`:
-
-                       .. math::
-                               x_o = g \\cosh(z_i) x_i + g \\sinh(z_i) y_i
-
-                               y_o = g \\sinh(z_i) x_i + g \\cosh(z_i) z_i
-
-               * vector-hyperbolic: natural logarithm `ln(), arctanh()`, and
-                 `sqrt()`. Use `x_i = a + b` and `y_i = a - b` to obtain `2*
-                 sqrt(a*b)` and `ln(a/b)/2`:
-
-                       .. math::
-                               x_o = g\\sqrt{x_i^2 - y_i^2}
-
-                               z_o = z_i + \\tanh^{-1}(y_i/x_i)
-
-               * rotate-linear: multiply and accumulate (not a very good
-                 multiplier implementation):
-
-                       .. math::
-                               y_o = g(y_i + x_i z_i)
-
-               * vector-linear: divide and accumulate:
-
-                       .. math::
-                               z_o = g(z_i + y_i/x_i)
-
-       Parameters
-       ----------
-       width : int
-               Bit width of the input and output signals. Defaults to 16. Input
-               and output signals are signed.
-       widthz : int
-               Bit with of `zi` and `zo`. Defaults to the `width`.
-       stages : int or None
-               Number of CORDIC incremental rotation stages. Defaults to
-               `width + min(1, guard)`.
-       guard : int or None
-               Add guard bits to the intermediate signals. If `None`,
-               defaults to `guard = log2(width)` which guarantees accuracy
-               to `width` bits.
-       eval_mode : str, {"iterative", "pipelined", "combinatorial"}
-       cordic_mode : str, {"rotate", "vector"}
-       func_mode : str, {"circular", "linear", "hyperbolic"}
-               Evaluation and arithmetic mode. See above.
-
-       Attributes
-       ----------
-       xi, yi, zi : Signal(width), in
-               Input values, signed.
-       xo, yo, zo : Signal(width), out
-               Output values, signed.
-       new_out : Signal(1), out
-               Asserted if output values are freshly updated in the current
-               cycle.
-       new_in : Signal(1), out
-               Asserted if new input values are being read in the next cycle.
-       zmax : float
-               `zi` and `zo` normalization factor. Floating point `zmax`
-               corresponds to `1<<(widthz - 1)`. `x` and `y` are scaled such
-               that floating point `1` corresponds to `1<<(width - 1)`.
-       gain : float
-               Cumulative, intrinsic gain and scaling factor. In circular mode
-               `sqrt(xi**2 + yi**2)` should be no larger than `2**(width - 1)/gain`
-               to prevent overflow. Additionally, in hyperbolic and linear mode,
-               the operation itself can cause overflow.
-       interval : int
-               Output interval in clock cycles. Inverse throughput.
-       latency : int
-               Input-to-output latency. The result corresponding to the inputs
-               appears at the outputs `latency` cycles later.
-
-       Notes
-       -----
-
-       Each stage `i` in the CORDIC performs the following operation:
-
-       .. math::
-               x_{i+1} = x_i - m d_i y_i r^{-s_{m,i}},
-
-               y_{i+1} = y_i + d_i x_i r^{-s_{m,i}},
-
-               z_{i+1} = z_i - d_i a_{m,i},
-
-       where:
-
-               * :math:`d_i`: clockwise or counterclockwise, determined by
-                 `sign(z_i)` in rotate mode or `sign(-y_i)` in vector mode.
-
-               * :math:`r`: radix of the number system (2)
-
-               * :math:`m`: 1: circular, 0: linear, -1: hyperbolic
-
-               * :math:`s_{m,i}`: non decreasing integer shift sequence
-
-               * :math:`a_{m,i}`: elemetary rotation angle: :math:`a_{m,i} =
-                 \\tan^{-1}(\\sqrt{m} s_{m,i})/\\sqrt{m}`.
-       """
-       def __init__(self, width=16, widthz=None, stages=None, guard=0,
-                       eval_mode="iterative", cordic_mode="rotate",
-                       func_mode="circular"):
-               # validate parameters
-               assert eval_mode in ("combinatorial", "pipelined", "iterative")
-               assert cordic_mode in ("rotate", "vector")
-               assert func_mode in ("circular", "linear", "hyperbolic")
-               self.cordic_mode = cordic_mode
-               self.func_mode = func_mode
-               if guard is None:
-                       # guard bits to guarantee "width" accuracy
-                       guard = int(log(width)/log(2))
-               if widthz is None:
-                       widthz = width
-               if stages is None:
-                       stages = width + min(1, guard) # cuts error below LSB
-
-               # input output interface
-               self.xi = Signal((width, True))
-               self.yi = Signal((width, True))
-               self.zi = Signal((widthz, True))
-               self.xo = Signal((width, True))
-               self.yo = Signal((width, True))
-               self.zo = Signal((widthz, True))
-               self.new_in = Signal()
-               self.new_out = Signal()
-
-               ###
-
-               a, s, self.zmax, self.gain = self._constants(stages, widthz + guard)
-               stages = len(a) # may have increased due to repetitions
-
-               if eval_mode == "iterative":
-                       num_sig = 3
-                       self.interval = stages + 1
-                       self.latency = stages + 2
-               else:
-                       num_sig = stages + 1
-                       self.interval = 1
-                       if eval_mode == "pipelined":
-                               self.latency = stages
-                       else: # combinatorial
-                               self.latency = 0
-
-               # inter-stage signals
-               x = [Signal((width + guard, True)) for i in range(num_sig)]
-               y = [Signal((width + guard, True)) for i in range(num_sig)]
-               z = [Signal((widthz + guard, True)) for i in range(num_sig)]
-
-               # hook up inputs and outputs to the first and last inter-stage
-               # signals
-               self.comb += [
-                       x[0].eq(self.xi<<guard),
-                       y[0].eq(self.yi<<guard),
-                       z[0].eq(self.zi<<guard),
-                       self.xo.eq(x[-1]>>guard),
-                       self.yo.eq(y[-1]>>guard),
-                       self.zo.eq(z[-1]>>guard),
-                       ]
-
-               if eval_mode == "iterative":
-                       # We afford one additional iteration for in/out.
-                       i = Signal(max=stages + 1)
-                       self.comb += [
-                                       self.new_in.eq(i == stages),
-                                       self.new_out.eq(i == 1),
-                                       ]
-                       ai = Signal((widthz + guard, True))
-                       self.sync += ai.eq(Array(a)[i])
-                       if range(stages) == s:
-                               si = i - 1 # shortcut if no stage repetitions
-                       else:
-                               si = Signal(max=stages + 1)
-                               self.sync += si.eq(Array(s)[i])
-                       xi, yi, zi = x[1], y[1], z[1]
-                       self.sync += [
-                                       self._stage(xi, yi, zi, xi, yi, zi, si, ai),
-                                       i.eq(i + 1),
-                                       If(i == stages,
-                                               i.eq(0),
-                                       ),
-                                       If(i == 0,
-                                               x[2].eq(xi),
-                                               y[2].eq(yi),
-                                               z[2].eq(zi),
-                                               xi.eq(x[0]),
-                                               yi.eq(y[0]),
-                                               zi.eq(z[0]),
-                                       )]
-               else:
-                       self.comb += [
-                                       self.new_out.eq(1),
-                                       self.new_in.eq(1),
-                                       ]
-                       for i, si in enumerate(s):
-                               stmt = self._stage(x[i], y[i], z[i],
-                                               x[i + 1], y[i + 1], z[i + 1], si, a[i])
-                               if eval_mode == "pipelined":
-                                       self.sync += stmt
-                               else: # combinatorial
-                                       self.comb += stmt
-
-       def _constants(self, stages, bits):
-               if self.func_mode == "circular":
-                       s = range(stages)
-                       a = [atan(2**-i) for i in s]
-                       g = [sqrt(1 + 2**(-2*i)) for i in s]
-                       #zmax = sum(a)
-                       # use pi anyway as the input z can cause overflow
-                       # and we need the range for quadrant mapping
-                       zmax = pi
-               elif self.func_mode == "linear":
-                       s = range(stages)
-                       a = [2**-i for i in s]
-                       g = [1 for i in s]
-                       #zmax = sum(a)
-                       # use 2 anyway as this simplifies a and scaling
-                       zmax = 2.
-               else: # hyperbolic
-                       s = []
-                       # need to repeat some stages:
-                       j = 4
-                       for i in range(stages):
-                               if i == j:
-                                       s.append(j)
-                                       j = 3*j + 1
-                               s.append(i + 1)
-                       a = [atanh(2**-i) for i in s]
-                       g = [sqrt(1 - 2**(-2*i)) for i in s]
-                       zmax = sum(a)*2
-               # round here helps the width=2**i - 1 case but hurts the
-               # important width=2**i case
-               cast = int
-               if log(bits)/log(2) % 1:
-                       cast = round
-               a = [cast(ai*2**(bits - 1)/zmax) for ai in a]
-               gain = 1.
-               for gi in g:
-                       gain *= gi
-               return a, s, zmax, gain
-
-       def _stage(self, xi, yi, zi, xo, yo, zo, i, ai):
-               dir = Signal()
-               if self.cordic_mode == "rotate":
-                       self.comb += dir.eq(zi < 0)
-               else: # vector
-                       self.comb += dir.eq(yi >= 0)
-               dx = yi>>i
-               dy = xi>>i
-               dz = ai
-               if self.func_mode == "linear":
-                       dx = 0
-               elif self.func_mode == "hyperbolic":
-                       dx = -dx
-               stmt = [
-                               xo.eq(xi + Mux(dir, dx, -dx)),
-                               yo.eq(yi + Mux(dir, -dy, dy)),
-                               zo.eq(zi + Mux(dir, dz, -dz))
-               ]
-               return stmt
-
-class Cordic(TwoQuadrantCordic):
-       """Four-quadrant CORDIC
-
-       Same as :class:`TwoQuadrantCordic` but with support and convergence
-       for `abs(zi) > pi/2 in circular rotate mode or `xi < 0` in circular
-       vector mode.
-       """
-       def __init__(self, **kwargs):
-               TwoQuadrantCordic.__init__(self, **kwargs)
-               if self.func_mode != "circular":
-                       return # no need to remap quadrants
-
-               cxi, cyi, czi = self.xi, self.yi, self.zi
-               self.xi = xi = Signal.like(cxi)
-               self.yi = yi = Signal.like(cyi)
-               self.zi = zi = Signal.like(czi)
-
-               ###
-
-               q = Signal()
-               if self.cordic_mode == "rotate":
-                       self.comb += q.eq(zi[-2] ^ zi[-1])
-               else: # vector
-                       self.comb += q.eq(xi < 0)
-               self.comb += [
-                               If(q,
-                                       Cat(cxi, cyi, czi).eq(Cat(-xi, -yi,
-                                               zi + (1 << flen(zi) - 1)))
-                               ).Else(
-                                       Cat(cxi, cyi, czi).eq(Cat(xi, yi, zi))
-                               )
-               ]