from ieee754.part_mul_add.adder import PartitionedAdder
from ieee754.part_cmp.eq_gt_ge import PartitionedEqGtGe
+from ieee754.part_shift.part_shift_dynamic import PartitionedDynamicShift
from ieee754.part_mul_add.partpoints import make_partition
from operator import or_, xor, and_, not_
# create partition points
self.partpoints = make_partition(mask, width)
self.modnames = {}
- for name in ['add', 'eq', 'gt', 'ge']:
+ for name in ['add', 'eq', 'gt', 'ge', 'ls']:
self.modnames[name] = 0
def set_module(self, m):
# TODO: detect if the 2nd operand is a Const, a Signal or a
# PartitionedSignal. if it's a Const or a Signal, a global shift
# can occur. if it's a PartitionedSignal, that's much more interesting.
+ def ls_op(self, op1, op2, carry):
+ op1 = getsig(op1)
+ op2 = getsig(op2)
+ shape = op1.shape()
+ pa = PartitionedDynamicShift(shape[0], self.partpoints)
+ setattr(self.m.submodules, self.get_modname('ls'), pa)
+ comb = self.m.d.comb
+ comb += pa.a.eq(op1)
+ comb += pa.b.eq(op2)
+ # XXX TODO: carry-in, carry-out
+ #comb += pa.carry_in.eq(carry)
+ return (pa.output, 0)
+
def __lshift__(self, other):
- raise NotImplementedError
- return Operator("<<", [self, other])
+ result, _ = self.ls_op(self, other, carry=0)
+ return result
def __rlshift__(self, other):
raise NotImplementedError
self.a = PartitionedSignal(partpoints, width)
self.b = PartitionedSignal(partpoints, width)
self.add_output = Signal(width)
+ self.ls_output = Signal(width) # left shift
self.sub_output = Signal(width)
self.eq_output = Signal(len(partpoints)+1)
self.gt_output = Signal(len(partpoints)+1)
comb = m.d.comb
self.a.set_module(m)
self.b.set_module(m)
+ # compares
comb += self.lt_output.eq(self.a < self.b)
comb += self.ne_output.eq(self.a != self.b)
comb += self.le_output.eq(self.a <= self.b)
self.carry_in)
comb += self.add_output.eq(add_out)
comb += self.add_carry_out.eq(add_carry)
+ # sub
sub_out, sub_carry = self.a.sub_op(self.a, self.b,
self.carry_in)
comb += self.sub_output.eq(sub_out)
comb += self.sub_carry_out.eq(sub_carry)
+ # neg
comb += self.neg_output.eq(-self.a)
+ # left shift
+ comb += self.ls_output.eq(self.a << self.b)
ppts = self.partpoints
comb += self.mux_out.eq(PMux(m, ppts, self.mux_sel, self.a, self.b))
def async_process():
+ def test_ls_fn(carry_in, a, b, mask):
+ # TODO: carry
+ carry_in = 0
+ lsb = mask & ~(mask-1) if carry_in else 0
+ sum = (a & mask) << (b & mask) + lsb
+ result = mask & sum
+ carry = (sum & mask) != sum
+ print(a, b, sum, mask)
+ return result, carry
+
def test_add_fn(carry_in, a, b, mask):
lsb = mask & ~(mask-1) if carry_in else 0
sum = (a & mask) + (b & mask) + lsb
result = mask & sum
carry = (sum & mask) != sum
+ carry = 0
print(a, b, sum, mask)
return result, carry
for (test_fn, mod_attr) in ((test_add_fn, "add"),
(test_sub_fn, "sub"),
(test_neg_fn, "neg"),
+ (test_ls_fn, "ls"),
):
yield part_mask.eq(0)
yield from test_op("16-bit", 1, test_fn, mod_attr, 0xFFFF)