"""
-from nmigen import Module, Signal, Cat, Const
+from nmigen import Module, Signal, Cat, Const, Mux
from nmigen.cli import main, verilog
from math import log
m = Module()
comb = m.d.comb
- # decode: XXX really should move to separate stage
+ # decode a/b
width = self.pspec.width
a1 = FPNumBaseRecord(width, False)
b1 = FPNumBaseRecord(width, False)
self.o.b.eq(b1)
]
- obz = Signal(reset_less=True)
- comb += obz.eq(a1.is_zero | b1.is_zero)
-
+ # intermediaries / tests
+ t_obz = Signal(reset_less=True)
+ t_a1inf = Signal(reset_less=True)
+ t_b1inf = Signal(reset_less=True)
+ t_abnan = Signal(reset_less=True)
+ t_special = Signal(reset_less=True)
sabx = Signal(reset_less=True) # sign a xor b (sabx, get it?)
- comb += sabx.eq(a1.s ^ b1.s)
- abnan = Signal(reset_less=True)
- comb += abnan.eq(a1.is_nan | b1.is_nan)
-
- # initialise and override if needed
- comb += self.o.out_do_z.eq(1)
+ comb += sabx.eq(a1.s ^ b1.s)
+ comb += t_obz.eq(a1.is_zero | b1.is_zero)
+ comb += t_a1inf.eq(a1.is_inf)
+ comb += t_b1inf.eq(b1.is_inf)
+ comb += t_abnan.eq(a1.is_nan | b1.is_nan)
+ comb += t_special.eq(Cat(t_obz, t_abnan, t_b1inf, t_a1inf).bool())
+
+ # prepare inf/zero/nans
+ z_zero = FPNumBaseRecord(width, False, name="z_zero")
+ z_nan = FPNumBaseRecord(width, False, name="z_nan")
+ z_inf = FPNumBaseRecord(width, False, name="z_inf")
+ comb += z_zero.zero(sabx)
+ comb += z_nan.nan(0)
+ comb += z_inf.inf(sabx)
+
+ # special case pipeline bypass enabled y/n
+ comb += self.o.out_do_z.eq(t_special)
# if a is NaN or b is NaN return NaN
- with m.If(abnan):
- comb += self.o.z.nan(0)
-
# if a is inf return inf (or NaN)
- with m.Elif(a1.is_inf):
- comb += self.o.z.inf(sabx)
- # b is zero return NaN
- with m.If(b1.is_zero):
- comb += self.o.z.nan(0)
-
+ # if b is zero return NaN
# if b is inf return inf (or NaN)
- with m.Elif(b1.is_inf):
- comb += self.o.z.inf(sabx)
- # a is zero return NaN
- with m.If(a1.is_zero):
- comb += self.o.z.nan(0)
-
+ # if a is zero return NaN
# if a is zero or b zero return signed-a/b
- with m.Elif(obz):
- comb += self.o.z.zero(sabx)
- # Denormalised Number checks next, so pass a/b data through
- with m.Else():
- comb += self.o.out_do_z.eq(0)
+ # invert the sequence above to create the Mux tree
+ # XXX TODO: use PriorityPicker?
+ oz = 0
+ oz = Mux(t_obz, z_zero.v, oz)
+ oz = Mux(t_b1inf, Mux(a1.is_zero, z_nan.v, z_inf.v), oz)
+ oz = Mux(t_a1inf, Mux(b1.is_zero, z_nan.v, z_inf.v), oz)
+ oz = Mux(t_abnan, z_nan.v, oz)
+ comb += self.o.oz.eq(oz)
- comb += self.o.oz.eq(self.o.z.v)
+ # pass through context
comb += self.o.ctx.eq(self.i.ctx)
return m