2013-11-30 08:55:01 -05:00
|
|
|
import unittest
|
|
|
|
from random import randrange, random
|
|
|
|
from math import *
|
|
|
|
|
|
|
|
from migen.fhdl.std import *
|
|
|
|
from migen.genlib.cordic import *
|
|
|
|
|
|
|
|
from migen.test.support import SimCase, SimBench
|
|
|
|
|
|
|
|
class CordicCase(SimCase, unittest.TestCase):
|
|
|
|
class TestBench(SimBench):
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
k = dict(width=8, guard=None, stages=None,
|
|
|
|
eval_mode="combinatorial", cordic_mode="rotate",
|
|
|
|
func_mode="circular")
|
|
|
|
k.update(kwargs)
|
|
|
|
self.submodules.dut = Cordic(**k)
|
|
|
|
|
|
|
|
def _run_io(self, n, gen, proc, delta=1, deltaz=1):
|
|
|
|
c = 2**(flen(self.tb.dut.xi) - 1)
|
|
|
|
g = self.tb.dut.gain
|
|
|
|
zm = self.tb.dut.zmax
|
|
|
|
pipe = {}
|
|
|
|
genn = [gen() for i in range(n)]
|
2014-01-26 16:19:43 -05:00
|
|
|
def cb(tb, tbp):
|
|
|
|
if tbp.dut.new_in:
|
2013-11-30 08:55:01 -05:00
|
|
|
if genn:
|
|
|
|
xi, yi, zi = genn.pop(0)
|
|
|
|
else:
|
2014-01-26 16:19:43 -05:00
|
|
|
raise StopSimulation
|
2013-11-30 08:55:01 -05:00
|
|
|
xi = floor(xi*c/g)
|
|
|
|
yi = floor(yi*c/g)
|
|
|
|
zi = floor(zi*c/zm)
|
2014-01-26 16:19:43 -05:00
|
|
|
tbp.dut.xi = xi
|
|
|
|
tbp.dut.yi = yi
|
|
|
|
tbp.dut.zi = zi
|
|
|
|
pipe[tbp.simulator.cycle_counter] = xi, yi, zi
|
|
|
|
if tbp.dut.new_out:
|
|
|
|
t = tbp.simulator.cycle_counter - tb.dut.latency - 1
|
2013-11-30 08:55:01 -05:00
|
|
|
if t < 1:
|
|
|
|
return
|
|
|
|
xi, yi, zi = pipe.pop(t)
|
|
|
|
xo, yo, zo = proc(xi/c, yi/c, zi/c*zm)
|
|
|
|
xo = floor(xo*c*g)
|
|
|
|
yo = floor(yo*c*g)
|
|
|
|
zo = floor(zo*c/zm)
|
2014-03-24 11:32:27 -04:00
|
|
|
xo1 = tbp.dut.xo
|
|
|
|
yo1 = tbp.dut.yo
|
|
|
|
zo1 = tbp.dut.zo
|
2013-11-30 08:55:01 -05:00
|
|
|
self.assertAlmostEqual(xo, xo1, delta=delta)
|
|
|
|
self.assertAlmostEqual(yo, yo1, delta=delta)
|
|
|
|
self.assertAlmostEqual(abs(zo - zo1) % (2*c), 0, delta=deltaz)
|
|
|
|
self.run_with(cb)
|
|
|
|
|
|
|
|
def test_rot_circ(self):
|
|
|
|
def gen():
|
|
|
|
ti = 2*pi*random()
|
|
|
|
r = random()*.98
|
|
|
|
return r*cos(ti), r*sin(ti), (2*random() - 1)*pi
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
xo = cos(zi)*xi - sin(zi)*yi
|
|
|
|
yo = sin(zi)*xi + cos(zi)*yi
|
|
|
|
return xo, yo, 0
|
|
|
|
self._run_io(50, gen, proc, delta=2)
|
|
|
|
|
|
|
|
def test_rot_circ_16(self):
|
|
|
|
self.setUp(width=16)
|
|
|
|
self.test_rot_circ()
|
|
|
|
|
|
|
|
def test_rot_circ_pipe(self):
|
|
|
|
self.setUp(eval_mode="pipelined")
|
|
|
|
self.test_rot_circ()
|
|
|
|
|
|
|
|
def test_rot_circ_iter(self):
|
|
|
|
self.setUp(eval_mode="iterative")
|
|
|
|
self.test_rot_circ()
|
|
|
|
|
|
|
|
def _test_vec_circ(self):
|
|
|
|
def gen():
|
|
|
|
ti = pi*(2*random() - 1)
|
|
|
|
r = .98 #*random()
|
|
|
|
return r*cos(ti), r*sin(ti), 0 #pi*(2*random() - 1)
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
return sqrt(xi**2 + yi**2), 0, zi + atan2(yi, xi)
|
|
|
|
self._run_io(50, gen, proc)
|
|
|
|
|
|
|
|
def test_vec_circ(self):
|
|
|
|
self.setUp(cordic_mode="vector")
|
|
|
|
self._test_vec_circ()
|
|
|
|
|
|
|
|
def test_vec_circ_16(self):
|
|
|
|
self.setUp(width=16, cordic_mode="vector")
|
|
|
|
self._test_vec_circ()
|
|
|
|
|
|
|
|
def _test_rot_hyp(self):
|
|
|
|
def gen():
|
|
|
|
return .6, 0, 2.1*(random() - .5)
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
xo = cosh(zi)*xi - sinh(zi)*yi
|
|
|
|
yo = sinh(zi)*xi + cosh(zi)*yi
|
|
|
|
return xo, yo, 0
|
|
|
|
self._run_io(50, gen, proc, delta=2)
|
|
|
|
|
|
|
|
def test_rot_hyp(self):
|
|
|
|
self.setUp(func_mode="hyperbolic")
|
|
|
|
self._test_rot_hyp()
|
|
|
|
|
|
|
|
def test_rot_hyp_16(self):
|
|
|
|
self.setUp(func_mode="hyperbolic", width=16)
|
|
|
|
self._test_rot_hyp()
|
|
|
|
|
|
|
|
def test_rot_hyp_iter(self):
|
|
|
|
self.setUp(cordic_mode="rotate", func_mode="hyperbolic",
|
|
|
|
eval_mode="iterative")
|
|
|
|
self._test_rot_hyp()
|
|
|
|
|
|
|
|
def _test_vec_hyp(self):
|
|
|
|
def gen():
|
|
|
|
xi = random()*.6 + .2
|
|
|
|
yi = random()*xi*.8
|
|
|
|
return xi, yi, 0
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
return sqrt(xi**2 - yi**2), 0, atanh(yi/xi)
|
|
|
|
self._run_io(50, gen, proc)
|
|
|
|
|
|
|
|
def test_vec_hyp(self):
|
|
|
|
self.setUp(cordic_mode="vector", func_mode="hyperbolic")
|
|
|
|
self._test_vec_hyp()
|
|
|
|
|
|
|
|
def _test_rot_lin(self):
|
|
|
|
def gen():
|
|
|
|
xi = 2*random() - 1
|
|
|
|
if abs(xi) < .01:
|
|
|
|
xi = .01
|
|
|
|
yi = (2*random() - 1)*.5
|
|
|
|
zi = (2*random() - 1)*.5
|
|
|
|
return xi, yi, zi
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
return xi, yi + xi*zi, 0
|
|
|
|
self._run_io(50, gen, proc)
|
|
|
|
|
|
|
|
def test_rot_lin(self):
|
|
|
|
self.setUp(func_mode="linear")
|
|
|
|
self._test_rot_lin()
|
|
|
|
|
|
|
|
def _test_vec_lin(self):
|
|
|
|
def gen():
|
|
|
|
yi = random()*.95 + .05
|
|
|
|
if random() > 0:
|
|
|
|
yi *= -1
|
|
|
|
xi = abs(yi) + random()*(1 - abs(yi))
|
|
|
|
zi = 2*random() - 1
|
|
|
|
return xi, yi, zi
|
|
|
|
def proc(xi, yi, zi):
|
|
|
|
return xi, 0, zi + yi/xi
|
|
|
|
self._run_io(50, gen, proc, deltaz=2, delta=2)
|
|
|
|
|
|
|
|
def test_vec_lin(self):
|
|
|
|
self.setUp(func_mode="linear", cordic_mode="vector", width=8)
|
|
|
|
self._test_vec_lin()
|