# IEEE Floating Point Conversion
# Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-from nmigen import Module, Signal, Cat
+from nmigen import Module, Signal, Cat, Mux
from nmigen.cli import main, verilog
from nmutil.pipemodbase import PipeModBase
-from ieee754.fpcommon.getop import FPADDBaseData
+from ieee754.fpcommon.basedata import FPBaseData
from ieee754.fpcommon.postcalc import FPPostCalcData
from ieee754.fpcommon.msbhigh import FPMSBHigh
-from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord
+from ieee754.fpcommon.fpbase import FPNumBaseRecord
class FPCVTIntToFloatMod(PipeModBase):
super().__init__(in_pspec, "intconvert")
def ispec(self):
- return FPADDBaseData(self.in_pspec)
+ return FPBaseData(self.in_pspec)
def ospec(self):
return FPPostCalcData(self.out_pspec, e_extra=True)
self.out_pspec.width)
print("a1", self.in_pspec.width)
z1 = self.o.z
+ a = self.i.a
print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end)
me = self.in_pspec.width
- mz = self.o.z.rmw
+ mz = z1.rmw
ms = mz - me
print("ms-me", ms, me, mz)
signed = Signal(reset_less=True)
comb += signed.eq(self.i.ctx.op[0])
- # copy of mantissa (one less bit if signed)
+ # mantissa (one less bit if signed), and sign
mantissa = Signal(me, reset_less=True)
+ sign = Signal(reset_less=True)
# detect signed/unsigned. key case: -ve numbers need inversion
# to +ve because the FP sign says if it's -ve or not.
- with m.If(signed):
- comb += z1.s.eq(self.i.a[-1]) # sign in top bit of a
- with m.If(z1.s):
- comb += mantissa.eq(-self.i.a) # invert input if sign -ve
- with m.Else():
- comb += mantissa.eq(self.i.a) # leave as-is
- with m.Else():
- comb += mantissa.eq(self.i.a) # unsigned, use full a
- comb += z1.s.eq(0)
+ comb += sign.eq(Mux(signed, a[-1], 0)) # sign in top bit of a
+ comb += mantissa.eq(Mux(signed,
+ Mux(sign, -a, # invert input if sign -ve
+ a), # leave as-is
+ a)) # unsigned, use full a
# set input from full INT
comb += msb.m_in.eq(Cat(0, 0, 0, mantissa)) # g/r/s + input
# smaller int to larger FP
comb += z1.e.eq(msb.e_out)
comb += z1.m[ms:].eq(msb.m_out[3:])
- comb += z1.create(z1.s, z1.e, z1.m) # ... here
+
+ # XXX there is some weirdness involving the sign looping back
+ # see graphviz output
+ # http://bugs.libre-riscv.org/show_bug.cgi?id=135
+ comb += z1.s.eq(sign)
+ comb += z1.create(sign, z1.e, z1.m) # ... here
# note: post-normalisation actually appears to be capable of
# detecting overflow to infinity (FPPackMod). so it's ok to
comb += self.o.of.sticky.eq(msb.m_out[:1].bool())
comb += self.o.of.m0.eq(msb.m_out[3])
- # special cases active by default
- comb += self.o.out_do_z.eq(1)
+ a_nonzero = Signal(reset_less=True)
+ comb += a_nonzero.eq(~a.bool())
+
+ # prepare zero
+ z_zero = FPNumBaseRecord(z1.width, False, name="z_zero")
+ comb += z_zero.zero(0)
+
+ # special cases?
+ comb += self.o.out_do_z.eq(a_nonzero)
# detect zero
- with m.If(~self.i.a.bool()):
- comb += self.o.z.zero(0)
- with m.Else():
- comb += self.o.out_do_z.eq(0) # activate normalisation
+ comb += self.o.oz.eq(Mux(a_nonzero, z1.v, z_zero.v))
# copy the context (muxid, operator)
- comb += self.o.oz.eq(self.o.z.v)
comb += self.o.ctx.eq(self.i.ctx)
return m