forgot other cordic files
This commit is contained in:
parent
e1702c422c
commit
a69741b24e
|
@ -1,63 +0,0 @@
|
|||
import copy
|
||||
import json
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.genlib.cordic import Cordic
|
||||
from mibuild.tools import mkdir_noerror
|
||||
from mibuild.generic_platform import *
|
||||
from mibuild.xilinx import XilinxPlatform
|
||||
|
||||
class CordicImpl(Module):
|
||||
def __init__(self, name, **kwargs):
|
||||
self.name = name
|
||||
mkdir_noerror("build")
|
||||
json.dump(kwargs, open("build/{}.json".format(name), "w"))
|
||||
self.platform = platform = Platform()
|
||||
self.submodules.cordic = Cordic(**kwargs)
|
||||
width = flen(self.cordic.xi)
|
||||
self.comb += self.cordic.xi.eq(
|
||||
int((1<<width - 1)/self.cordic.gain*.98))
|
||||
self.comb += self.cordic.yi.eq(0)
|
||||
zi = self.cordic.zi
|
||||
self.sync += zi.eq(zi + 1)
|
||||
do = platform.request("do")
|
||||
self.sync += do.eq(Cat(self.cordic.xo, self.cordic.yo))
|
||||
|
||||
def build(self):
|
||||
self.platform.build(self, build_name=self.name)
|
||||
|
||||
class Platform(XilinxPlatform):
|
||||
default_clk_name = "clk"
|
||||
default_clk_period = 20.0
|
||||
|
||||
_io = [
|
||||
("clk", 0, Pins("AB13")),
|
||||
("do", 0,
|
||||
Pins("Y2 W3 W1 P8 P7 P6 P5 T4 T3",
|
||||
"U4 V3 N6 N7 M7 M8 R4 P4 M6 L6 P3 N4",
|
||||
"M5 V2 V1 U3 U1 T2 T1 R3 R1 P2 P1"),
|
||||
),
|
||||
]
|
||||
def __init__(self):
|
||||
XilinxPlatform.__init__(self, "xc6slx45-fgg484-2", self._io)
|
||||
|
||||
if __name__ == "__main__":
|
||||
default = dict(width=16, guard=0, eval_mode="pipelined",
|
||||
func_mode="circular", cordic_mode="rotate")
|
||||
variations = dict(
|
||||
eval_mode=["combinatorial", "pipelined", "iterative"],
|
||||
width=[4, 8, 12, 14, 16, 20, 24, 32],
|
||||
stages=[10, 12, 14, 16, 20, 24, 32],
|
||||
guard=[0, 1, 2, 3, 4],
|
||||
)
|
||||
CordicImpl("cordic_test", eval_mode="combinatorial").build()
|
||||
|
||||
name = "cordic_baseline"
|
||||
CordicImpl(name, **default).build()
|
||||
|
||||
for k, v in sorted(variations.items()):
|
||||
for vi in v:
|
||||
name = "cordic_{}_{}".format(k, vi)
|
||||
kw = copy.copy(default)
|
||||
kw[k] = vi
|
||||
CordicImpl(name, **kw).build()
|
|
@ -1,71 +0,0 @@
|
|||
import glob, os, re, json
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas
|
||||
|
||||
|
||||
def extract(b, n, r, c=int):
|
||||
r = re.compile(r)
|
||||
try:
|
||||
f = open(b + n)
|
||||
except:
|
||||
return
|
||||
for l in f:
|
||||
m = r.search(l)
|
||||
if m:
|
||||
v = m.groups()[0]
|
||||
v = v.replace(",", "")
|
||||
return c(v)
|
||||
|
||||
def load(prefix, base):
|
||||
kw = json.load(open(base))
|
||||
b = os.path.splitext(base)[0]
|
||||
_, n = os.path.split(b)[1].split("_", 1)
|
||||
try:
|
||||
n, _ = n.rsplit("_", 1)
|
||||
kw["vary"] = n
|
||||
except:
|
||||
pass
|
||||
kw["slack"] = extract(b, ".par",
|
||||
"GRPclk.*SETUP +\\| +([\d,]+\\.\d+)", float)
|
||||
kw["freq"] = extract(b, ".srp",
|
||||
"Maximum Frequency: +([\d,]+\\.\d+) *MHz", float)
|
||||
kw["reg"] = extract(b, "_map.mrp",
|
||||
"Number of Slice Registers: +([\d,]+) ")
|
||||
kw["lut"] = extract(b, "_map.mrp",
|
||||
"Number of Slice LUTs: +([\d,]+) ")
|
||||
kw["slice"] = extract(b, "_map.mrp",
|
||||
"Number of occupied Slices: +([\d,]+) ")
|
||||
return kw
|
||||
|
||||
def run(prefix):
|
||||
dat = {}
|
||||
for base in glob.glob("build/{}_*.json".format(prefix)):
|
||||
kw = load(prefix, base)
|
||||
if "vary" in kw:
|
||||
dat[base] = kw
|
||||
df = pandas.DataFrame.from_dict(dat, orient="index")
|
||||
comp = "freq slice slack".split()
|
||||
dfg = df.groupby("vary")
|
||||
fig, ax = plt.subplots(len(dfg), len(comp))
|
||||
for axj, (v, dfi) in zip(ax, dfg):
|
||||
print(v, dfi)
|
||||
if v not in dfi:
|
||||
continue
|
||||
dfi = dfi.sort(v)
|
||||
for axi, n in zip(axj, comp):
|
||||
x = dfi[v]
|
||||
if type(x[0]) is type(""):
|
||||
xi = range(len(x))
|
||||
axi.set_xticks(xi)
|
||||
axi.set_xticklabels(x)
|
||||
x = xi
|
||||
axi.plot(x, dfi[n])
|
||||
axi.set_xlabel(v)
|
||||
axi.set_ylabel(n)
|
||||
fig.savefig("cordic_impl.pdf")
|
||||
plt.show()
|
||||
|
||||
if __name__ == "__main__":
|
||||
run("cordic")
|
|
@ -1,109 +0,0 @@
|
|||
import random
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.fhdl import verilog
|
||||
from migen.genlib.cordic import Cordic
|
||||
from migen.sim.generic import run_simulation
|
||||
|
||||
class TestBench(Module):
|
||||
def __init__(self, n=None, xmax=.98, i=None, **kwargs):
|
||||
self.submodules.cordic = Cordic(**kwargs)
|
||||
if n is None:
|
||||
n = 1<<flen(self.cordic.xi)
|
||||
self.c = c = 2**(flen(self.cordic.xi) - 1)
|
||||
self.cz = cz = 2**(flen(self.cordic.zi) - 1)
|
||||
x = int(xmax*c/self.cordic.gain)
|
||||
if i is None:
|
||||
i = [(x, 0, int(cz*(2.*ii/n - 1))) for ii in range(n)]
|
||||
self.i = i
|
||||
random.shuffle(self.i)
|
||||
self.ii = iter(self.i)
|
||||
self.o = []
|
||||
|
||||
def do_simulation(self, selfp):
|
||||
if selfp.cordic.new_out:
|
||||
self.o.append((selfp.cordic.xo, selfp.cordic.yo, selfp.cordic.zo))
|
||||
if selfp.cordic.new_in:
|
||||
try:
|
||||
selfp.cordic.xi, selfp.cordic.yi, selfp.cordic.zi = next(self.ii)
|
||||
except StopIteration:
|
||||
raise StopSimulation
|
||||
|
||||
def run_io(self):
|
||||
run_simulation(self)
|
||||
del self.o[0]
|
||||
if self.i[0] != (0, 0, 0):
|
||||
assert self.o[0] != (0, 0, 0)
|
||||
#if self.i[-1] != self.i[-2]:
|
||||
# assert self.o[-1] != self.o[-2], self.o[-2:]
|
||||
|
||||
def rms_err(width, guard=None, stages=None, n=None):
|
||||
tb = TestBench(width=width, guard=guard, stages=stages,
|
||||
n=n, eval_mode="combinatorial")
|
||||
tb.run_io()
|
||||
c = 2**(flen(tb.cordic.xi) - 1)
|
||||
cz = 2**(flen(tb.cordic.zi) - 1)
|
||||
g = tb.cordic.gain
|
||||
xi, yi, zi = np.array(tb.i).T/c
|
||||
zi *= c/cz*tb.cordic.zmax
|
||||
xo1, yo1, zo1 = np.array(tb.o).T
|
||||
xo = np.floor(c*g*(np.cos(zi)*xi - np.sin(zi)*yi))
|
||||
yo = np.floor(c*g*(np.sin(zi)*xi + np.cos(zi)*yi))
|
||||
dx = xo1 - xo
|
||||
dy = yo1 - yo
|
||||
mm = np.fabs([dx, dy]).max()
|
||||
rms = np.sqrt(dx**2 + dy**2).sum()/len(xo)
|
||||
return rms, mm
|
||||
|
||||
def rms_err_map():
|
||||
widths, stages = np.mgrid[8:33:1, 8:37:1]
|
||||
errf = np.vectorize(lambda w, s: rms_err(int(w), None, int(s), n=333))
|
||||
err = errf(widths, stages)
|
||||
print(err)
|
||||
lev = np.arange(10)
|
||||
fig, ax = plt.subplots()
|
||||
c1 = ax.contour(widths, stages, err[0], lev/10, cmap=plt.cm.Greys_r)
|
||||
c2 = ax.contour(widths, stages, err[1], lev, cmap=plt.cm.Reds_r)
|
||||
ax.plot(widths[:, 0], stages[0, np.argmin(err[0], 1)], "ko")
|
||||
ax.plot(widths[:, 0], stages[0, np.argmin(err[1], 1)], "ro")
|
||||
print(widths[:, 0], stages[0, np.argmin(err[0], 1)],
|
||||
stages[0, np.argmin(err[1], 1)])
|
||||
ax.set_xlabel("width")
|
||||
ax.set_ylabel("stages")
|
||||
ax.grid("on")
|
||||
fig.colorbar(c1)
|
||||
fig.colorbar(c2)
|
||||
fig.savefig("cordic_rms.pdf")
|
||||
|
||||
def plot_function(**kwargs):
|
||||
tb = TestBench(eval_mode="combinatorial", **kwargs)
|
||||
tb.run_io()
|
||||
c = 2**(flen(tb.cordic.xi) - 1)
|
||||
cz = 2**(flen(tb.cordic.zi) - 1)
|
||||
g = tb.cordic.gain
|
||||
xi, yi, zi = np.array(tb.i).T
|
||||
xo, yo, zo = np.array(tb.o).T
|
||||
fig, ax = plt.subplots()
|
||||
#ax.plot(zi, xo-np.around(xi[0]*g*np.cos(zi/cz*np.pi)), "k-")
|
||||
ax.plot(zi, xo, "r,")
|
||||
ax.plot(zi, yo, "g,")
|
||||
ax.plot(zi, zo, "b,")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = Cordic(width=16, guard=None, eval_mode="combinatorial")
|
||||
print(verilog.convert(c, ios={c.xi, c.yi, c.zi, c.xo, c.yo, c.zo,
|
||||
c.new_in, c.new_out}))
|
||||
#print(rms_err(8))
|
||||
#rms_err_map()
|
||||
#plot_function(func_mode="hyperbolic", xmax=.3, width=16, n=333)
|
||||
#plot_function(func_mode="circular", width=16, n=333)
|
||||
#plot_function(func_mode="hyperbolic", cordic_mode="vector",
|
||||
# xmax=.3, width=16, n=333)
|
||||
plot_function(func_mode="circular",
|
||||
width=16, stages=15, guard=0,
|
||||
n=1000, xmax=.98)
|
||||
plt.show()
|
|
@ -1,160 +0,0 @@
|
|||
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)]
|
||||
def cb(tb, tbp):
|
||||
if tbp.dut.new_in:
|
||||
if genn:
|
||||
xi, yi, zi = genn.pop(0)
|
||||
else:
|
||||
raise StopSimulation
|
||||
xi = floor(xi*c/g)
|
||||
yi = floor(yi*c/g)
|
||||
zi = floor(zi*c/zm)
|
||||
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
|
||||
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)
|
||||
xo1 = tbp.dut.xo
|
||||
yo1 = tbp.dut.yo
|
||||
zo1 = tbp.dut.zo
|
||||
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, deltaz=2)
|
||||
|
||||
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()
|
Loading…
Reference in New Issue