examples/cordic: scripted exploration of parameters space
authorRobert Jordens <jordens@gmail.com>
Mon, 2 Dec 2013 02:30:49 +0000 (19:30 -0700)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 2 Dec 2013 11:56:29 +0000 (12:56 +0100)
examples/cordic/cordic_impl.py [new file with mode: 0644]
examples/cordic/cordic_impl_eval.py [new file with mode: 0644]

diff --git a/examples/cordic/cordic_impl.py b/examples/cordic/cordic_impl.py
new file mode 100644 (file)
index 0000000..d7ac084
--- /dev/null
@@ -0,0 +1,61 @@
+import copy
+import json
+
+from migen.fhdl.std import *
+from migen.genlib.cordic import Cordic
+from mibuild.generic_platform import *
+from mibuild.xilinx_ise import XilinxISEPlatform, CRG_SE
+
+
+class CordicImpl(Module):
+       def __init__(self, name, **kwargs):
+               self.name = name
+               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(XilinxISEPlatform):
+       _io = [
+               ("clk", 0, Pins("AB13")),
+               ("rst", 0, Pins("V5")),
+               ("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):
+               XilinxISEPlatform.__init__(self, "xc6slx45-fgg484-2", self._io,
+                       lambda p: CRG_SE(p, "clk", "rst", 10.))
+
+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()
diff --git a/examples/cordic/cordic_impl_eval.py b/examples/cordic/cordic_impl_eval.py
new file mode 100644 (file)
index 0000000..eeefffb
--- /dev/null
@@ -0,0 +1,71 @@
+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")