def setup(self, m, i):
""" links module to inputs and outputs
"""
- m.submodules.upconvert = self
+ m.submodules.intconvert = self
m.d.comb += self.i.eq(i)
def process(self, i):
print("z1", z1.width, z1.rmw, z1.e_width, z1.e_start, z1.e_end)
me = self.in_pspec.width
- ms = self.o.z.rmw - me
- print("ms-me", ms, me, self.o.z.rmw)
+ mz = self.o.z.rmw
+ ms = mz - me
+ print("ms-me", ms, me, mz)
# 3 extra bits for guard/round/sticky
msb = FPMSBHigh(me+3, z1.e_width)
# conversion can mostly be done manually...
zo = self.o.z
m.d.comb += zo.s.eq(0) # unsigned for now
- m.d.comb += zo.e.eq(msb.e_out)
- m.d.comb += zo.m[ms:].eq(msb.m_out[3:])
+ if ms < 0:
+ # larger int to smaller FP (uint32/64 -> fp16 most likely)
+ m.d.comb += zo.e.eq(msb.e_out-1)
+ m.d.comb += zo.m[ms-1:].eq(msb.m_out[-mz-1:])
+ else:
+ # smaller int to larger FP
+ m.d.comb += zo.e.eq(msb.e_out)
+ m.d.comb += zo.m[ms:].eq(msb.m_out[3:])
m.d.comb += zo.create(zo.s, zo.e, zo.m) # ... here
# initialise rounding (but only activate if needed)
- m.d.comb += self.o.of.guard.eq(msb.m_out[2])
- m.d.comb += self.o.of.round_bit.eq(msb.m_out[1])
- m.d.comb += self.o.of.sticky.eq(msb.m_out[1])
- m.d.comb += self.o.of.m0.eq(msb.m_out[3])
+ if ms < 0:
+ # larger int to smaller FP (uint32/64 -> fp16 most likely)
+ m.d.comb += self.o.of.guard.eq(msb.m_out[-mz-2])
+ m.d.comb += self.o.of.round_bit.eq(msb.m_out[-mz-3])
+ m.d.comb += self.o.of.sticky.eq(msb.m_out[:-mz-3].bool())
+ m.d.comb += self.o.of.m0.eq(msb.m_out[-mz-1])
+ else:
+ # smaller int to larger FP
+ m.d.comb += self.o.of.guard.eq(msb.m_out[2])
+ m.d.comb += self.o.of.round_bit.eq(msb.m_out[1])
+ m.d.comb += self.o.of.sticky.eq(msb.m_out[:1].bool())
+ m.d.comb += self.o.of.m0.eq(msb.m_out[3])
# special cases active by default
m.d.comb += self.o.out_do_z.eq(1)
def to_uint32(x):
return x
+def to_uint64(x):
+ return x
+
def fcvt_64(x):
return sfpy.float.ui32_to_f64(x)
def fcvt_32(x):
return sfpy.float.ui32_to_f32(x)
-def test_int_pipe_fp16_32():
+def fcvt_16(x):
+ return sfpy.float.ui32_to_f16(x)
+
+def test_int_pipe_ui16_f32():
+ # XXX softfloat-3 doesn't have ui16_to_xxx so use ui32 instead.
+ # should be fine.
dut = FPCVTIntMuxInOut(16, 32, 4)
- runfp(dut, 16, "test_fcvt_int_pipe_fp16_32", to_uint16, fcvt_32, True,
+ runfp(dut, 16, "test_fcvt_int_pipe_ui16_f32", to_uint16, fcvt_32, True,
n_vals=100)
-def test_int_pipe_fp16_64():
+def test_int_pipe_ui16_f64():
dut = FPCVTIntMuxInOut(16, 64, 4)
- runfp(dut, 16, "test_fcvt_int_pipe_fp16_64", to_uint16, fcvt_64, True,
+ runfp(dut, 16, "test_fcvt_int_pipe_ui16_f64", to_uint16, fcvt_64, True,
n_vals=100)
-def test_int_pipe_fp32_64():
+def test_int_pipe_ui32_f64():
dut = FPCVTIntMuxInOut(32, 64, 4)
- runfp(dut, 32, "test_fcvt_int_pipe_fp32_64", to_uint32, fcvt_64, True,
+ runfp(dut, 32, "test_fcvt_int_pipe_ui32_64", to_uint32, fcvt_64, True,
+ n_vals=100)
+
+def test_int_pipe_ui64_f16():
+ # ok, doing 17 bits here because it's pretty pointless (not entirely)
+ # to do random numbers statistically likely 99.999% of the time to be
+ # converted to Inf
+ dut = FPCVTIntMuxInOut(64, 16, 4)
+ runfp(dut, 17, "test_fcvt_int_pipe_ui64_16", to_uint64, fcvt_16, True,
+ n_vals=100)
+
+def test_int_pipe_ui32_f16():
+ # ok, doing 17 bits here because it's pretty pointless (not entirely)
+ # to do random numbers statistically likely 99.999% of the time to be
+ # converted to Inf
+ dut = FPCVTIntMuxInOut(32, 16, 4)
+ runfp(dut, 17, "test_fcvt_int_pipe_ui32_16", to_uint32, fcvt_16, True,
n_vals=100)
if __name__ == '__main__':
for i in range(200):
- test_int_pipe_fp16_32()
- test_int_pipe_fp16_64()
- test_int_pipe_fp32_64()
+ test_int_pipe_ui32_f16()
+ test_int_pipe_ui64_f16()
+ test_int_pipe_ui16_f32()
+ test_int_pipe_ui16_f64()
+ test_int_pipe_ui32_f64()