+
+class MultiShiftR:
+
+ def __init__(self, width):
+ self.width = width
+ self.smax = int(log(width) / log(2))
+ self.i = Signal(width, reset_less=True)
+ self.s = Signal(self.smax, reset_less=True)
+ self.o = Signal(width, reset_less=True)
+
+ def elaborate(self, platform):
+ m = Module()
+ m.d.comb += self.o.eq(self.i >> self.s)
+ return m
+
+
+class MultiShift:
+ """ Generates variable-length single-cycle shifter from a series
+ of conditional tests on each bit of the left/right shift operand.
+ Each bit tested produces output shifted by that number of bits,
+ in a binary fashion: bit 1 if set shifts by 1 bit, bit 2 if set
+ shifts by 2 bits, each partial result cascading to the next Mux.
+
+ Could be adapted to do arithmetic shift by taking copies of the
+ MSB instead of zeros.
+ """
+
+ def __init__(self, width):
+ self.width = width
+ self.smax = int(log(width) / log(2))
+
+ def lshift(self, op, s):
+ res = op << s
+ return res[:len(op)]
+ res = op
+ for i in range(self.smax):
+ zeros = [0] * (1<<i)
+ res = Mux(s & (1<<i), Cat(zeros, res[0:-(1<<i)]), res)
+ return res
+
+ def rshift(self, op, s):
+ res = op >> s
+ return res[:len(op)]
+ res = op
+ for i in range(self.smax):
+ zeros = [0] * (1<<i)
+ res = Mux(s & (1<<i), Cat(res[(1<<i):], zeros), res)
+ return res
+
+
+class FPNumBase: #(Elaboratable):
+ """ Floating-point Base Number Class
+ """
+ def __init__(self, width, m_extra=True):
+ self.width = width
+ m_width = {16: 11, 32: 24, 64: 53}[width] # 1 extra bit (overflow)
+ e_width = {16: 7, 32: 10, 64: 13}[width] # 2 extra bits (overflow)
+ e_max = 1<<(e_width-3)
+ self.rmw = m_width # real mantissa width (not including extras)
+ self.e_max = e_max
+ if m_extra:
+ # mantissa extra bits (top,guard,round)
+ self.m_extra = 3
+ m_width += self.m_extra
+ else:
+ self.m_extra = 0
+ #print (m_width, e_width, e_max, self.rmw, self.m_extra)
+ self.m_width = m_width
+ self.e_width = e_width
+ self.e_start = self.rmw - 1
+ self.e_end = self.rmw + self.e_width - 3 # for decoding
+
+ self.v = Signal(width, reset_less=True) # Latched copy of value
+ self.m = Signal(m_width, reset_less=True) # Mantissa
+ self.e = Signal((e_width, True), reset_less=True) # Exponent: IEEE754exp+2 bits, signed
+ self.s = Signal(reset_less=True) # Sign bit
+
+ self.mzero = Const(0, (m_width, False))
+ m_msb = 1<<(self.m_width-2)
+ self.msb1 = Const(m_msb, (m_width, False))
+ self.m1s = Const(-1, (m_width, False))
+ self.P128 = Const(e_max, (e_width, True))
+ self.P127 = Const(e_max-1, (e_width, True))
+ self.N127 = Const(-(e_max-1), (e_width, True))
+ self.N126 = Const(-(e_max-2), (e_width, True))
+
+ self.is_nan = Signal(reset_less=True)
+ self.is_zero = Signal(reset_less=True)
+ self.is_inf = Signal(reset_less=True)
+ 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)
+ 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_nan.eq(self._is_nan())
+ m.d.comb += self.is_zero.eq(self._is_zero())
+ m.d.comb += self.is_inf.eq(self._is_inf())
+ 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_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)
+ 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.exp_128) & (~self.m_zero)
+
+ def _is_inf(self):
+ return (self.exp_128) & (self.m_zero)
+
+ def _is_zero(self):
+ return (self.exp_n127) & (self.m_zero)
+
+ def _is_overflowed(self):
+ return self.exp_gt127
+
+ def _is_denormalised(self):
+ return (self.exp_n126) & (self.m_msbzero)
+
+ def __iter__(self):
+ yield self.s
+ yield self.e
+ yield self.m
+
+ def eq(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