[libre-riscv-dev] [Bug 208] implement CORDIC in a general way sufficient to do transcendentals
bugzilla-daemon at libre-soc.org
bugzilla-daemon at libre-soc.org
Mon Apr 13 18:23:10 BST 2020
https://bugs.libre-soc.org/show_bug.cgi?id=208
--- Comment #4 from Luke Kenneth Casson Leighton <lkcl at lkcl.net> ---
(In reply to Michael Nolan from comment #3)
> I was able to translate the linked myhdl code to nmigen and implement both a
> state machine based and pipelined cordic here:
> https://git.libre-soc.org/?p=ieee754fpu.git;a=tree;f=src/ieee754/cordic;
> h=3f06900baa42651410d661739fb616e4b3020c52;
> hb=77f150cff440bed025e2487b6f0fcda9f529290b
cool! well that was easy :)
> You can configure the width, as well as the number of cordic rounds per
> pipeline stage. There are some accuracy issues with it though - it exactly
> matches the behavior of the myhdl one, but the results it gives can be off
> by 1% or so from that obtained using sin() or cos() on 16 bit numbers.
yes. i believe it's well-known that to get 16-bit accuracy you need
32-bit registers.
i made a couple of corrections btw - frickin well done for working out
the pipeline API with zero assistance - that's deeply impressive given
that, other than the docstring comments, there's no "documentation" on
it.
CordicInitialData needed to "yield self.z0" (not self.z)
"yield from" is reserved for a way to yield *from* something that is
itself iteratable (such as another function). self.z0 is in fact
iterable, so what would be returned by "yield from" would be first
self.z0[0], then on the next iteration self.z0[1] and so on which
would be very painful.
"yield" just returns "that object".
however... we have a bit of a problem back in nmutil.iocontrol NextControl
and PrevControl iteration, in that it can't actually properly work out
if the *object* that you are iterating should be yielded or yielded *from*.
so i added a hack "check if data has a ports function".
however i've just right now worked out that we could detect if the object
is iterable with isinstance(self.data_o, Iterable).
so that's just been committed.
i also added an rtlil test because i was fascinated to see what the
graphviz looks like.
--- a/src/ieee754/cordic/pipe_data.py
+++ b/src/ieee754/cordic/pipe_data.py
@@ -10,11 +10,14 @@ class CordicInitialData:
self.z0 = Signal(range(-ZMAX, ZMAX), name="z") # denormed result
def __iter__(self):
- yield from self.z
+ yield self.z0
def eq(self, i):
return [self.z0.eq(i.z0)]
class CordicData:
@@ -27,9 +30,12 @@ class CordicData:
self.z = Signal(range(-ZMAX, ZMAX), name="z") # denormed result
def __iter__(self):
- yield from self.x
- yield from self.y
- yield from self.z
+ yield self.x
+ yield self.y
+ yield self.z
def eq(self, i):
ret = [self.z.eq(i.z), self.x.eq(i.x), self.y.eq(i.y)]
diff --git a/src/ieee754/cordic/test/test_pipe.py
b/src/ieee754/cordic/test/test_pipe.py
index 880351a..b7eaf8a 100644
--- a/src/ieee754/cordic/test/test_pipe.py
+++ b/src/ieee754/cordic/test/test_pipe.py
@@ -1,6 +1,7 @@
from nmigen import Module, Signal
from nmigen.back.pysim import Simulator, Passive
from nmigen.test.utils import FHDLTestCase
+from nmigen.cli import rtlil
from ieee754.cordic.sin_cos_pipeline import CordicBasePipe
from ieee754.cordic.pipe_data import CordicPipeSpec
@@ -16,6 +17,13 @@ class SinCosTestCase(FHDLTestCase):
pspec = CordicPipeSpec(fracbits=fracbits, rounds_per_stage=4)
m.submodules.dut = dut = CordicBasePipe(pspec)
+ for port in dut.ports():
+ print ("port", port)
+
+ vl = rtlil.convert(dut, ports=dut.ports())
+ with open("test_cordic_pipe_sin_cos.il", "w") as f:
+ f.write(vl)
+
z = Signal(dut.p.data_i.z0.shape())
z_valid = Signal()
ready = Signal()
(END)
--
You are receiving this mail because:
You are on the CC list for the bug.
More information about the libre-riscv-dev
mailing list