add signed/unsigned functions and preliminary unit test
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 5 Oct 2021 16:42:43 +0000 (17:42 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Tue, 5 Oct 2021 16:42:43 +0000 (17:42 +0100)
src/ieee754/part/partsig.py
src/ieee754/part/test/test_partsig.py

index 5d3ba756ee204c2cfe939669a7c9e0a704ed5813..d2b6280df00874871ea2208b12cce51a037af0a7 100644 (file)
@@ -30,7 +30,7 @@ from ieee754.part_cat.pcat import PCat
 from operator import or_, xor, and_, not_
 
 from nmigen import (Signal, Const)
-from nmigen.hdl.ast import UserValue
+from nmigen.hdl.ast import UserValue, Shape
 
 
 def getsig(op1):
@@ -342,9 +342,16 @@ class PartitionedSignal(UserValue):
     # TODO, http://bugs.libre-riscv.org/show_bug.cgi?id=716
     # def __getitem__(self, key):
 
-    # TODO, http://bugs.libre-riscv.org/show_bug.cgi?id=719
-    #def as_unsigned(self):
-    #def as_signed(self):
+    def __new_sign(self, signed):
+        shape = Shape(len(self), signed=signed)
+        result = PartitionedSignal.like(self, shape=shape)
+        self.m.d.comb += result.sig.eq(self.sig)
+        return result
+
+    def as_unsigned(self):
+        return self.__new_sign(False)
+    def as_signed(self):
+        return self.__new_sign(True)
 
     # useful operators
 
index 965d0eca898e237c5fb1465a3a7cb760f25344f4..dff2d6ec847a7b7538db3b61f087b23d80328247 100644 (file)
@@ -202,6 +202,7 @@ class TestAddMod(Elaboratable):
         self.add_carry_out = Signal(len(partpoints)+1)
         self.sub_carry_out = Signal(len(partpoints)+1)
         self.neg_output = Signal(width)
+        self.signed_output = Signal(width)
         self.xor_output = Signal(len(partpoints)+1)
         self.bool_output = Signal(len(partpoints)+1)
         self.all_output = Signal(len(partpoints)+1)
@@ -230,8 +231,9 @@ class TestAddMod(Elaboratable):
                                            self.carry_in)
         comb += self.sub_output.eq(sub_out.sig)
         comb += self.sub_carry_out.eq(sub_carry)
-        # neg
+        # neg / signed / unsigned
         comb += self.neg_output.eq((-self.a).sig)
+        comb += self.signed_output.eq(self.a.as_signed())
         # horizontal operators
         comb += self.xor_output.eq(self.a.xor())
         comb += self.bool_output.eq(self.a.bool())
@@ -749,6 +751,9 @@ class TestPartitionedSignal(unittest.TestCase):
                 a = (a & mask) >> pos  # shift it to the beginning
                 return ((-a) << pos) & mask, 0  # negate and shift it back
 
+            def test_signed_fn(carry_in, a, b, mask):
+                return a & mask, 0
+
             def test_op(msg_prefix, carry, test_fn, mod_attr, *mask_list):
                 rand_data = []
                 for i in range(100):
@@ -801,6 +806,7 @@ class TestPartitionedSignal(unittest.TestCase):
                                         (test_add_fn, "add"),
                                         (test_sub_fn, "sub"),
                                         (test_neg_fn, "neg"),
+                                        (test_signed_fn, "signed"),
                                         ):
                 yield part_mask.eq(0)
                 yield from test_op("16-bit", 1, test_fn, mod_attr, 0xFFFF)