self.is_overflowed = Signal(reset_less=True)
self.is_denormalised = Signal(reset_less=True)
self.exp_128 = Signal(reset_less=True)
+ self.exp_gt_n126 = Signal(reset_less=True)
+ self.exp_gt127 = Signal(reset_less=True)
+ self.exp_n127 = Signal(reset_less=True)
+ self.exp_n126 = Signal(reset_less=True)
+ self.m_zero = Signal(reset_less=True)
+ self.m_msbzero = Signal(reset_less=True)
def elaborate(self, platform):
m = Module()
m.d.comb += self.is_overflowed.eq(self._is_overflowed())
m.d.comb += self.is_denormalised.eq(self._is_denormalised())
m.d.comb += self.exp_128.eq(self.e == self.P128)
+ m.d.comb += self.exp_gt_n126.eq(self.e > self.N126)
+ m.d.comb += self.exp_gt127.eq(self.e > self.P127)
+ m.d.comb += self.exp_n127.eq(self.e == self.N127)
+ m.d.comb += self.exp_n126.eq(self.e == self.N126)
+ m.d.comb += self.m_zero.eq(self.m == self.mzero)
+ m.d.comb += self.m_msbzero.eq(self.m[self.e_start] == 0)
return m
def _is_nan(self):
- return (self.e == self.P128) & (self.m != 0)
+ return (self.exp_128) & (~self.m_zero)
def _is_inf(self):
- return (self.e == self.P128) & (self.m == 0)
+ return (self.exp_128) & (self.m_zero)
def _is_zero(self):
- return (self.e == self.N127) & (self.m == self.mzero)
+ return (self.exp_n127) & (self.m_zero)
def _is_overflowed(self):
- return (self.e > self.P127)
+ return self.exp_gt127
def _is_denormalised(self):
- return (self.e == self.N126) & (self.m[self.e_start] == 0)
+ return (self.exp_n126) & (self.m_msbzero)
+
+ def copy(self, inp):
+ return [self.s.eq(inp.s), self.e.eq(inp.e), self.m.eq(inp.m)]
class FPNumOut(FPNumBase):
- """ Floating-point Number Class, variable-width TODO (currently 32-bit)
+ """ Floating-point Number Class
Contains signals for an incoming copy of the value, decoded into
sign / exponent / mantissa.
return self.create(s, self.N127, 0)
+class FPNumShift(FPNumBase):
+ """ Floating-point Number Class for shifting
+ """
+ def __init__(self, mainm, op, inv, width, m_extra=True):
+ FPNumBase.__init__(self, width, m_extra)
+ self.latch_in = Signal()
+ self.mainm = mainm
+ self.inv = inv
+ self.op = op
+
+ def elaborate(self, platform):
+ m = FPNumBase.elaborate(self, platform)
+
+ m.d.comb += self.s.eq(op.s)
+ m.d.comb += self.e.eq(op.e)
+ m.d.comb += self.m.eq(op.m)
+
+ with self.mainm.State("align"):
+ with m.If(self.e < self.inv.e):
+ m.d.sync += self.shift_down()
+
+ return m
+
+ def shift_down(self):
+ """ shifts a mantissa down by one. exponent is increased to compensate
+
+ accuracy is lost as a result in the mantissa however there are 3
+ guard bits (the latter of which is the "sticky" bit)
+ """
+ return [self.e.eq(self.e + 1),
+ self.m.eq(Cat(self.m[0] | self.m[1], self.m[2:], 0))
+ ]
+
+ def shift_down_multi(self, diff):
+ """ shifts a mantissa down. exponent is increased to compensate
+
+ accuracy is lost as a result in the mantissa however there are 3
+ guard bits (the latter of which is the "sticky" bit)
+
+ this code works by variable-shifting the mantissa by up to
+ its maximum bit-length: no point doing more (it'll still be
+ zero).
+
+ the sticky bit is computed by shifting a batch of 1s by
+ the same amount, which will introduce zeros. it's then
+ inverted and used as a mask to get the LSBs of the mantissa.
+ those are then |'d into the sticky bit.
+ """
+ sm = MultiShift(self.width)
+ mw = Const(self.m_width-1, len(diff))
+ maxslen = Mux(diff > mw, mw, diff)
+ rs = sm.rshift(self.m[1:], maxslen)
+ maxsleni = mw - maxslen
+ m_mask = sm.rshift(self.m1s[1:], maxsleni) # shift and invert
+
+ stickybits = reduce(or_, self.m[1:] & m_mask) | self.m[0]
+ return [self.e.eq(self.e + diff),
+ self.m.eq(Cat(stickybits, rs))
+ ]
+
+ def shift_up_multi(self, diff):
+ """ shifts a mantissa up. exponent is decreased to compensate
+ """
+ sm = MultiShift(self.width)
+ mw = Const(self.m_width, len(diff))
+ maxslen = Mux(diff > mw, mw, diff)
+
+ return [self.e.eq(self.e - diff),
+ self.m.eq(sm.lshift(self.m, maxslen))
+ ]
+
class FPNumIn(FPNumBase):
- """ Floating-point Number Class, variable-width TODO (currently 32-bit)
+ """ Floating-point Number Class
Contains signals for an incoming copy of the value, decoded into
sign / exponent / mantissa.
def elaborate(self, platform):
m = FPNumBase.elaborate(self, platform)
- m.d.comb += self.latch_in.eq(self.op.ack & self.op.stb)
- with m.If(self.latch_in):
- m.d.sync += self.decode(self.v)
+ #m.d.comb += self.latch_in.eq(self.op.ack & self.op.stb)
+ #with m.If(self.latch_in):
+ # m.d.sync += self.decode(self.v)
return m
self.width = width
self.v = Signal(width)
- self.stb = Signal()
+ self.stb = Signal(reset=0)
self.ack = Signal()
+ def chain_inv(self, in_op, extra=None):
+ stb = in_op.stb
+ if extra is not None:
+ stb = stb & extra
+ return [self.v.eq(in_op.v), # receive value
+ self.stb.eq(stb), # receive STB
+ in_op.ack.eq(~self.ack), # send ACK
+ ]
+
+ def chain_from(self, in_op, extra=None):
+ stb = in_op.stb
+ if extra is not None:
+ stb = stb & extra
+ return [self.v.eq(in_op.v), # receive value
+ self.stb.eq(stb), # receive STB
+ in_op.ack.eq(self.ack), # send ACK
+ ]
+
def ports(self):
return [self.v, self.stb, self.ack]
self.roundz = Signal(reset_less=True)
+ def copy(self, inp):
+ return [self.guard.eq(inp.guard),
+ self.round_bit.eq(inp.round_bit),
+ self.sticky.eq(inp.sticky),
+ self.m0.eq(inp.m0)]
+
def elaborate(self, platform):
m = Module()
m.d.comb += self.roundz.eq(self.guard & \
m.next = next_state
m.d.sync += [
# op is latched in from FPNumIn class on same ack/stb
+ v.decode(op.v),
op.ack.eq(0)
]
with m.Else():
with m.Else():
m.next = next_state
- def roundz(self, m, z, of, next_state):
+ def roundz(self, m, z, out_z, roundz):
""" performs rounding on the output. TODO: different kinds of rounding
"""
- m.next = next_state
- with m.If(of.roundz):
- m.d.sync += z.m.eq(z.m + 1) # mantissa rounds up
+ m.d.comb += out_z.copy(z) # copies input to output first
+ with m.If(roundz):
+ m.d.comb += out_z.m.eq(z.m + 1) # mantissa rounds up
with m.If(z.m == z.m1s): # all 1s
- m.d.sync += z.e.eq(z.e + 1) # exponent rounds up
+ m.d.comb += out_z.e.eq(z.e + 1) # exponent rounds up
def corrections(self, m, z, next_state):
""" denormalisation and sign-bug corrections