From 881e211655f3d339cc343f48bc12822b298ce644 Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Thu, 16 Apr 2020 13:14:43 -0400 Subject: [PATCH] Assert that fpsin_cos converts floats to fixed correctly --- src/ieee754/cordic/fpsin_cos.py | 23 ++++++++++++++++---- src/ieee754/cordic/test/test_fpsin_cos.py | 26 +++++++++++++++-------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/ieee754/cordic/fpsin_cos.py b/src/ieee754/cordic/fpsin_cos.py index 96df0d45..fa7ed8c1 100644 --- a/src/ieee754/cordic/fpsin_cos.py +++ b/src/ieee754/cordic/fpsin_cos.py @@ -2,7 +2,7 @@ # later be used to verify the operation of a pipelined version # see http://bugs.libre-riscv.org/show_bug.cgi?id=208 -from nmigen import Module, Elaboratable, Signal, Memory +from nmigen import Module, Elaboratable, Signal, Memory, Cat, Repl, Mux from nmigen.cli import rtlil import math from enum import Enum, unique @@ -44,10 +44,11 @@ class CORDIC(Elaboratable): def __init__(self, width): self.z0 = Signal(width, name="z0") - self.z_record = FPNumBaseRecord(self.z0.width, m_extra=True) + self.z_record = FPNumBaseRecord(self.z0.width, False, name="z_record") self.fracbits = 2 * self.z_record.m_width self.M = M = (1 << self.fracbits) self.ZMAX = int(round(self.M * math.pi/2)) + self.z_out = Signal(range(-self.ZMAX, self.ZMAX-1)) # sin/cos output in 0.ffffff format self.cos = Signal(range(-M, M+1), reset=0) @@ -98,15 +99,29 @@ class CORDIC(Elaboratable): comb += self.sin.eq(y) with m.If(state == CordicState.WAITING): with m.If(self.start): + z_intermed = Signal(z_fixed.shape()) + shifter = Signal(z_in.e.width) + comb += shifter.eq(-z_in.e) + # This converts z_in.m to a large fixed point + # integer. Right now, I'm ignoring denormals but they + # will be added back in when I convert this to the + # pipelined implementation (and I can use FPAddDenormMod) + comb += z_intermed.eq(Cat(Repl(0, self.fracbits - z_in.rmw), + z_in.m[:-1], 1)) + sync += z_fixed.eq(z_intermed >> shifter) sync += state.eq(CordicState.INIT) - sync += z_fixed.eq(z_in.m << (self.fracbits - z_in.rmw)) + sync += self.ready.eq(0) with m.If(state == CordicState.INIT): + z_temp = Signal(z.shape(), reset_less=True) + comb += z_temp.eq(Mux(z_in.s, ~z_fixed + 1, z_fixed)) + sync += z.eq(z_temp) + sync += self.z_out.eq(z_temp) sync += x.eq(X0) sync += y.eq(0) - sync += z.eq(z_fixed) sync += i.eq(0) sync += state.eq(CordicState.RUNNING) sync += anglerom.addr.eq(1) + sync += self.ready.eq(1) # debug with m.If(state == CordicState.RUNNING): with m.If(z >= 0): sync += x.eq(x - dx) diff --git a/src/ieee754/cordic/test/test_fpsin_cos.py b/src/ieee754/cordic/test/test_fpsin_cos.py index 25b97a56..1f050960 100644 --- a/src/ieee754/cordic/test/test_fpsin_cos.py +++ b/src/ieee754/cordic/test/test_fpsin_cos.py @@ -16,7 +16,7 @@ class SinCosTestCase(FHDLTestCase): m = Module() - m.submodules.dut = dut = CORDIC(32) + m.submodules.dut = dut = CORDIC(16) z = Signal(dut.z0.width) start = Signal() @@ -35,6 +35,7 @@ class SinCosTestCase(FHDLTestCase): sim.add_clock(1e-6) def process(): + asserted = False yield z.eq(zin.get_bits()) yield start.eq(1) @@ -43,6 +44,12 @@ class SinCosTestCase(FHDLTestCase): yield for i in range(fracbits * 3): rdy = yield ready + zo = yield dut.z_out + if rdy and not asserted: + frac = self.get_frac(zo, dut.z_out.width - 2) + print(f"{zo:x} {frac}") + self.assertEqual(str(frac), zin.__str__()) + asserted = True yield sim.add_sync_process(process) @@ -54,20 +61,21 @@ class SinCosTestCase(FHDLTestCase): self.run_test(zin=z, fracbits=fracbits) def test_1(self): - x = Float32(1.0) + x = Float16(.31212) + print(x) self.run_test_assert(x) # def test_neg(self): # self.run_test_assert(-6) - # def test_rand(self): - # fracbits = 16 - # M = (1 << fracbits) - # ZMAX = int(round(M * math.pi/2)) - # for i in range(500): - # z = random.randrange(-ZMAX, ZMAX-1) - # self.run_test_assert(z, fracbits=fracbits) + def test_rand(self): + for i in range(500): + z = random.uniform(-1, 1) + f = Float16(z) + self.run_test_assert(f) + def get_frac(self, value, bits): + return value/(1 << bits) if __name__ == "__main__": unittest.main() -- 2.30.2