self.is_overflowed = Signal(reset_less=True)
self.is_denormalised = Signal(reset_less=True)
self.exp_128 = Signal(reset_less=True)
+ self.exp_sub_n126 = Signal((e_width, True), reset_less=True)
+ self.exp_lt_n126 = 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)
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_sub_n126.eq(self.e - self.N126)
+ m.d.comb += self.exp_gt_n126.eq(self.exp_sub_n126 > 0)
+ m.d.comb += self.exp_lt_n126.eq(self.exp_sub_n126 < 0)
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)
return self.create(s, self.N127, 0)
+class MultiShiftRMerge:
+ """ shifts down (right) and merges lower bits into m[0].
+ m[0] is the "sticky" bit, basically
+ """
+ def __init__(self, width):
+ self.smax = int(log(width) / log(2))
+ self.m = Signal(width, reset_less=True)
+ self.inp = Signal(width, reset_less=True)
+ self.diff = Signal(self.smax, reset_less=True)
+ self.width = width
+
+ def elaborate(self, platform):
+ m = Module()
+
+ rs = Signal(self.width, reset_less=True)
+ m_mask = Signal(self.width, reset_less=True)
+ smask = Signal(self.width, reset_less=True)
+ stickybit = Signal(reset_less=True)
+
+ sm = MultiShift(self.width-1)
+ m0s = Const(0, self.width-1)
+ mw = Const(self.width-1, len(self.diff))
+ maxslen = Mux(self.diff > mw, mw, self.diff)
+ maxsleni = mw - maxslen
+ m.d.comb += [
+ # shift mantissa by maxslen, mask by inverse
+ rs.eq(sm.rshift(self.inp[1:], maxslen)),
+ m_mask.eq(sm.rshift(~m0s, maxsleni)),
+ smask.eq(self.inp[1:] & m_mask),
+ # sticky bit combines all mask (and mantissa low bit)
+ stickybit.eq(smask.bool() | self.inp[0]),
+ # mantissa result contains m[0] already.
+ self.m.eq(Cat(stickybit, rs))
+ ]
+ return m
+
+
class FPNumShift(FPNumBase):
""" Floating-point Number Class for shifting
"""
return m
- def shift_down(self):
+ def shift_down(self, inp):
""" 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))
+ return [self.e.eq(inp.e + 1),
+ self.m.eq(Cat(inp.m[0] | inp.m[1], inp.m[2:], 0))
]
def shift_down_multi(self, diff):
self.s.eq(v[-1]), # sign
]
- def shift_down(self):
+ def shift_down(self, inp):
""" 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))
+ return [self.e.eq(inp.e + 1),
+ self.m.eq(Cat(inp.m[0] | inp.m[1], inp.m[2:], 0))
]
- def shift_down_multi(self, diff):
+ def shift_down_multi(self, diff, inp=None):
""" shifts a mantissa down. exponent is increased to compensate
accuracy is lost as a result in the mantissa however there are 3
inverted and used as a mask to get the LSBs of the mantissa.
those are then |'d into the sticky bit.
"""
+ if inp is None:
+ inp = self
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)
+ rs = sm.rshift(inp.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),
+ #stickybits = reduce(or_, inp.m[1:] & m_mask) | inp.m[0]
+ stickybits = (inp.m[1:] & m_mask).bool() | inp.m[0]
+ return [self.e.eq(inp.e + diff),
self.m.eq(Cat(stickybits, rs))
]
self.v = Signal(width)
self.stb = Signal(reset=0)
self.ack = Signal()
+ self.trigger = Signal(reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+ m.d.sync += self.trigger.eq(self.stb & self.ack)
+ return m
def chain_inv(self, in_op, extra=None):
stb = in_op.stb
in_op.ack.eq(self.ack), # send ACK
]
+ def copy(self, inp):
+ return [self.v.eq(inp.v),
+ self.stb.eq(inp.stb),
+ self.ack.eq(inp.ack)
+ ]
+
def ports(self):
return [self.v, self.stb, self.ack]
both cases *effectively multiply the number stored by 2*,
which has to be taken into account when extracting the result.
"""
- with m.If(a.e == a.N127):
+ with m.If(a.exp_n127):
m.d.sync += a.e.eq(a.N126) # limit a exponent
with m.Else():
m.d.sync += a.m[-1].eq(1) # set top mantissa bit