self.add_carry_out = Signal(len(partpoints)+1)
self.sub_carry_out = Signal(len(partpoints)+1)
self.neg_output = Signal(width)
+ self.xor_output = Signal(len(partpoints)+1)
def elaborate(self, platform):
m = Module()
comb += self.sub_carry_out.eq(sub_carry)
# neg
comb += self.neg_output.eq((-self.a).sig)
+ # horizontal operators
+ comb += self.xor_output.eq(self.a.xor())
# left shift
comb += self.ls_output.eq(self.a << self.b)
# right shift
def async_process():
+ def test_xor_fn(a, mask):
+ test = (a & mask)
+ result = 0
+ while test != 0:
+ bit = (test & 1)
+ result ^= bit
+ test >>= 1
+ return result
+
+ def test_horizop(msg_prefix, test_fn, mod_attr, *maskbit_list):
+ randomvals = []
+ for i in range(10):
+ randomvals.append(randint(0, 65535))
+ for a in [0x0000,
+ 0x1234,
+ 0xABCD,
+ 0xFFFF,
+ 0x8000,
+ 0xBEEF, 0xFEED,
+ ]+randomvals:
+ yield module.a.lower().eq(a)
+ yield Delay(0.1e-6)
+ # convert to mask_list
+ mask_list = []
+ for mb in maskbit_list:
+ v = 0
+ for i in range(4):
+ if mb & (1 << i):
+ v |= 0xf << (i*4)
+ mask_list.append(v)
+ y = 0
+ # do the partitioned tests
+ for i, mask in enumerate(mask_list):
+ if test_fn(a, mask):
+ # OR y with the lowest set bit in the mask
+ y |= maskbit_list[i]
+ # check the result
+ outval = (yield getattr(module, "%s_output" % mod_attr))
+ msg = f"{msg_prefix}: {mod_attr} 0x{a:X} " + \
+ f" => 0x{y:X} != 0x{outval:X}, masklist %s"
+ print((msg % str(maskbit_list)).format(locals()))
+ self.assertEqual(y, outval, msg % str(maskbit_list))
+
+ for (test_fn, mod_attr) in ((test_xor_fn, "xor"),
+ #(test_ne_fn, "ne"),
+ ):
+ yield part_mask.eq(0)
+ yield from test_horizop("16-bit", test_fn, mod_attr, 0b1111)
+ yield part_mask.eq(0b10)
+ yield from test_horizop("8-bit", test_fn, mod_attr,
+ 0b1100, 0b0011)
+ yield part_mask.eq(0b1111)
+ yield from test_horizop("4-bit", test_fn, mod_attr,
+ 0b1000, 0b0100, 0b0010, 0b0001)
+
def test_ls_scal_fn(carry_in, a, b, mask):
# reduce range of b
bits = count_bits(mask)