From: Michael Nolan Date: Sun, 2 Feb 2020 16:21:01 +0000 (-0500) Subject: Begin adding FPCMP module (FEQ, FLT, FLE) X-Git-Tag: ls180-24jan2020~300 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=37046d3559d8c4249a0ce3b20a29cc3d20ce8b5b;p=ieee754fpu.git Begin adding FPCMP module (FEQ, FLT, FLE) --- diff --git a/src/ieee754/fpcmp/fpcmp.py b/src/ieee754/fpcmp/fpcmp.py new file mode 100644 index 00000000..1b0629f5 --- /dev/null +++ b/src/ieee754/fpcmp/fpcmp.py @@ -0,0 +1,55 @@ +# IEEE Floating Point Conversion, FSGNJ +# Copyright (C) 2019 Luke Kenneth Casson Leighton +# Copyright (C) 2020 Michael Nolan + + +from nmigen import Module, Signal, Mux + +from nmutil.pipemodbase import PipeModBase +from ieee754.fpcommon.basedata import FPBaseData +from ieee754.fpcommon.packdata import FPPackData +from ieee754.fpcommon.fpbase import FPNumDecode, FPNumBaseRecord + + +class FPCMPPipeMod(PipeModBase): + """ + Floating point comparison: FEQ, FLT, FLE + Opcodes (funct3): + - 0b00 - FLE - floating point less than or equal to + - 0b01 - FLT - floating point less than + - 0b10 - FEQ - floating equals + """ + def __init__(self, in_pspec): + self.in_pspec = in_pspec + super().__init__(in_pspec, "fpcmp") + + def ispec(self): + return FPBaseData(self.in_pspec) + + def ospec(self): + return FPPackData(self.in_pspec) + + def elaborate(self, platform): + m = Module() + + # useful clarity variables + comb = m.d.comb + width = self.pspec.width + opcode = self.i.ctx.op + z1 = self.o.z + + a1 = FPNumBaseRecord(width, False) + b1 = FPNumBaseRecord(width, False) + m.submodules.sc_decode_a = a1 = FPNumDecode(None, a1) + m.submodules.sc_decode_b = b1 = FPNumDecode(None, b1) + + m.d.comb += [a1.v.eq(self.i.a), + b1.v.eq(self.i.b)] + + + comb += z1.eq(0) + + # copy the context (muxid, operator) + comb += self.o.ctx.eq(self.i.ctx) + + return m diff --git a/src/ieee754/fpcmp/pipeline.py b/src/ieee754/fpcmp/pipeline.py new file mode 100644 index 00000000..57fa9105 --- /dev/null +++ b/src/ieee754/fpcmp/pipeline.py @@ -0,0 +1,56 @@ +"""IEEE754 Floating Point Conversion + +Copyright (C) 2019 Luke Kenneth Casson Leighton +Copyright (C) 2020 Michael Nolan + +""" + +from nmutil.singlepipe import ControlBase +from nmutil.concurrentunit import ReservationStations, num_bits + +from ieee754.pipeline import PipelineSpec, DynamicPipe + +from ieee754.fpcmp.fpcmp import FPCMPPipeMod + + +class FPCMPStage(DynamicPipe): + """ FPConversion and De-norm + """ + + def __init__(self, in_pspec): + stage = FPCMPPipeMod(in_pspec) + in_pspec.stage = stage + super().__init__(in_pspec) + + +class FPCMPBasePipe(ControlBase): + def __init__(self, pspec): + ControlBase.__init__(self) + self.pipe1 = FPCMPStage(pspec) + self._eqs = self.connect([self.pipe1, ]) + + def elaborate(self, platform): + m = ControlBase.elaborate(self, platform) + m.submodules.fpcmp = self.pipe1 + m.d.comb += self._eqs + return m + + +class FPCMPMuxInOut(ReservationStations): + """ Reservation-Station version of FPCVT pipeline. + + * fan-in on inputs (an array of FPBaseData: a,b,mid) + * converter pipeline (alu) + * fan-out on outputs (an array of FPPackData: z,mid) + + Fan-in and Fan-out are combinatorial. + """ + + def __init__(self, in_width, num_rows, op_wid=1): + self.op_wid = op_wid + self.id_wid = num_bits(num_rows) + + self.in_pspec = PipelineSpec(in_width, self.id_wid, self.op_wid) + + self.alu = FPCMPBasePipe(self.in_pspec) + ReservationStations.__init__(self, num_rows) diff --git a/src/ieee754/fpcmp/test/test_fpcmp_pipe.py b/src/ieee754/fpcmp/test/test_fpcmp_pipe.py new file mode 100644 index 00000000..5fd05945 --- /dev/null +++ b/src/ieee754/fpcmp/test/test_fpcmp_pipe.py @@ -0,0 +1,32 @@ +""" test of FPCVTMuxInOut +""" + +from ieee754.fpcmp.pipeline import (FPCMPMuxInOut) +from ieee754.fpcommon.test.fpmux import runfp + +from sfpy import Float16, Float32, Float64 +import math + + +def fpcmp_eq(a, b): + return Float32(a.eq(b)) + +def fpcmp_lt(a, b): + return Float32(a.lt(b)) + + +def test_fpcmp_eq(): + dut = FPCMPMuxInOut(32, 4) + runfp(dut, 32, "test_fpcmp_eq", Float32, fpcmp_eq, + n_vals=100, opcode=0b10) + +def test_fpcmp_lt(): + dut = FPCMPMuxInOut(32, 4) + runfp(dut, 32, "test_fpcmp_lt", Float32, fpcmp_lt, + n_vals=100, opcode=0b00) + + +if __name__ == '__main__': + for i in range(50): + test_fpcmp_lt() + test_fpcmp_eq()