forked from M-Labs/artiq
70 lines
2.1 KiB
Python
70 lines
2.1 KiB
Python
from operator import add
|
|
from functools import reduce
|
|
|
|
from migen import *
|
|
|
|
|
|
class Delay(Module):
|
|
def __init__(self, i, delay, o=None):
|
|
if isinstance(i, (int, tuple)):
|
|
z = [Signal(i) for j in range(delay + 1)]
|
|
elif isinstance(i, list):
|
|
z = [Record(i) for j in range(delay + 1)]
|
|
elif isinstance(i, Record):
|
|
z = [Record(i.layout) for j in range(delay + 1)]
|
|
else:
|
|
z = [Signal.like(i) for j in range(delay + 1)]
|
|
self.i = z[0]
|
|
self.o = z[-1]
|
|
if not isinstance(i, (int, list, tuple)):
|
|
self.comb += self.i.eq(i)
|
|
if o is not None:
|
|
self.comb += o.eq(self.o)
|
|
self.latency = delay
|
|
self.sync += [z[j + 1].eq(z[j]) for j in range(delay)]
|
|
|
|
|
|
def eqh(a, b):
|
|
return a[-len(b):].eq(b[-len(a):])
|
|
|
|
|
|
class SatAddMixin:
|
|
"""Signed saturating addition mixin"""
|
|
def sat_add(self, a, width, limits=None, clipped=None):
|
|
a = list(a)
|
|
# assert all(value_bits_sign(ai)[1] for ai in a)
|
|
max_width = max(value_bits_sign(ai)[0] for ai in a)
|
|
carry = log2_int(len(a), need_pow2=False)
|
|
full = Signal((max_width + carry, True))
|
|
limited = Signal((width, True))
|
|
carry = len(full) - width
|
|
assert carry >= 0
|
|
clip = Signal(2)
|
|
sign = Signal()
|
|
if clipped is not None:
|
|
self.comb += clipped.eq(clip)
|
|
self.comb += [
|
|
full.eq(reduce(add, a)),
|
|
sign.eq(full[-1]),
|
|
limited.eq(full)
|
|
]
|
|
if limits is None:
|
|
self.comb += [
|
|
If(full[-1-carry:] != Replicate(sign, carry + 1),
|
|
clip.eq(Cat(sign, ~sign)),
|
|
limited.eq(Cat(Replicate(~sign, width - 1), sign)),
|
|
)
|
|
]
|
|
else:
|
|
self.comb += [
|
|
If(full < limits[0],
|
|
clip.eq(0b01),
|
|
limited.eq(limits[0])
|
|
),
|
|
If(full > limits[1],
|
|
clip.eq(0b10),
|
|
limited.eq(limits[1]),
|
|
)
|
|
]
|
|
return limited
|