add less-than, greater-than, signed, and le/ge
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 3 Apr 2020 14:20:30 +0000 (15:20 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 3 Apr 2020 14:20:38 +0000 (15:20 +0100)
src/soc/decoder/power_pseudo.py
src/soc/decoder/pseudo/lexer.py
src/soc/decoder/pseudo/parser.py
src/soc/decoder/selectable_int.py

index e5d1a9697600bcc0032a61b6289f4a72c70da094..78add9ef67ec672b91bb97138267122739209356 100644 (file)
@@ -70,7 +70,7 @@ else if a > EXTS(SI) then
 """
 
 cmpi = """
-CR[0:1] <- c
+RA[0:1] <- 0b11
 """
 
 
@@ -194,6 +194,10 @@ def test():
             yield Delay(1e-6)
 
             # read regs, drop them into dict for function
+            for rname in gsc.parser.uninit_regs:
+                d[rname] = SelectableInt(0, 64) # uninitialised (to zero)
+                print ("uninitialised", rname, get_reg_hex(d[rname]))
+
             for rname in gsc.parser.read_regs:
                 regidx = yield getattr(decode.sigforms['X'], rname)
                 d[rname] = gsc.gpr[regidx]
index ba517c4fd67390605bce7c8718f8205645b184e2..992ab7b638a95c46704de2c860381c9b42e8c404 100644 (file)
@@ -241,6 +241,10 @@ class PowerLexer:
         'COLON',
         'EQ',
         'ASSIGN',
+        'LTU',
+        'GTU',
+        'LE',
+        'GE',
         'LT',
         'GT',
         'PLUS',
@@ -283,6 +287,10 @@ class PowerLexer:
     t_COLON = r':'
     t_EQ = r'='
     t_ASSIGN = r'<-'
+    t_LTU = r'<u'
+    t_GTU = r'>u'
+    t_LE = r'<='
+    t_GE = r'>='
     t_LT = r'<'
     t_GT = r'>'
     t_PLUS = r'\+'
index 3d487aaf46a026e7f8cb68e34e30dc3def8a4b57..8ce1b8c2e3322d2b9ba42a51e139f00822c7afbd 100644 (file)
@@ -41,6 +41,18 @@ def Assign(left, right):
         return ast.Assign([ast.AssTuple(ass_list)], right)
     elif isinstance(left, ast.Subscript):
         return ast.Assign([left], right)
+        # XXX HMMM probably not needed...
+        ls = left.slice
+        if isinstance(ls, ast.Slice):
+            lower, upper, step = ls.lower, ls.upper, ls.step
+            print ("slice assign", lower, upper, step)
+            if step is None:
+                ls = (lower, upper, None)
+            else:
+                ls = (lower, upper, step)
+            ls = ast.Tuple(ls)
+        return ast.Call(ast.Name("selectassign"),
+                        [left.value, ls, right], [])
     else:
         print ("Assign fail")
         raise SyntaxError("Can't do that yet")
@@ -66,6 +78,12 @@ def Assign(left, right):
 # factor: ('+'|'-'|'~') factor | power
 # comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
 
+def make_le_compare(arg):
+    (left, right) = arg
+    return ast.Compare(left, [ast.Le()], [right])
+def make_ge_compare(arg):
+    (left, right) = arg
+    return ast.Compare(left, [ast.Ge()], [right])
 def make_lt_compare(arg):
     (left, right) = arg
     return ast.Compare(left, [ast.Lt()], [right])
@@ -81,6 +99,8 @@ binary_ops = {
     "-": ast.Sub(),
     "*": ast.Mult(),
     "/": ast.Div(),
+    "<=": make_le_compare,
+    ">=": make_ge_compare,
     "<": make_lt_compare,
     ">": make_gt_compare,
     "=": make_eq_compare,
@@ -108,7 +128,7 @@ def check_concat(node): # checks if the comparison is already a concat
 class PowerParser:
 
     precedence = (
-        ("left", "EQ", "GT", "LT"),
+        ("left", "EQ", "GT", "LT", "LE", "GE", "LTU", "GTU"),
         ("left", "PLUS", "MINUS"),
         ("left", "MULT", "DIV"),
         )
@@ -118,6 +138,7 @@ class PowerParser:
         for rname in ['RA', 'RB', 'RC', 'RT', 'RS']:
             self.gprs[rname] = None
         self.read_regs = []
+        self.uninit_regs = []
         self.write_regs = []
 
     # The grammar comments come from Python's Grammar/Grammar file
@@ -227,6 +248,8 @@ class PowerParser:
                 name = p[1].id
             elif isinstance(p[1], ast.Subscript):
                 name = p[1].value.id
+                if name in self.gprs:
+                    self.uninit_regs.append(name) # add to list of uninitialised
             print ("expr assign", name, p[1])
             if name in self.gprs:
                 self.write_regs.append(name) # add to list of regs to write
@@ -308,8 +331,12 @@ class PowerParser:
                       | comparison MINUS comparison
                       | comparison MULT comparison
                       | comparison DIV comparison
-                      | comparison LT comparison
                       | comparison EQ comparison
+                      | comparison LE comparison
+                      | comparison GE comparison
+                      | comparison LTU comparison
+                      | comparison GTU comparison
+                      | comparison LT comparison
                       | comparison GT comparison
                       | PLUS comparison
                       | MINUS comparison
@@ -317,7 +344,11 @@ class PowerParser:
                       | power"""
         if len(p) == 4:
             print (list(p))
-            if p[2] == '||':
+            if p[2] == '<u':
+                p[0] = ast.Call(ast.Name("ltu"), (p[1], p[3]), [])
+            elif p[2] == '>u':
+                p[0] = ast.Call(ast.Name("gtu"), (p[1], p[3]), [])
+            elif p[2] == '||':
                 l = check_concat(p[1]) + check_concat(p[3])
                 p[0] = ast.Call(ast.Name("concat"), l, [])
             elif p[2] in ['<', '>', '=']:
index 4ca2de366b1cf012c046d96bbfe12bc912847987..5a18833017de2956eb54b786758b0b0bc579700d 100644 (file)
@@ -89,9 +89,42 @@ class SelectableInt:
             value = value << start
             self.value = (self.value & ~mask) | (value & mask)
 
+    def __ge__(self, other):
+        if isinstance(other, SelectableInt):
+            assert other.bits == self.bits
+            other = other.value
+        if isinstance(other, int):
+            return other >= self.value
+        assert False
+
+    def __le__(self, other):
+        if isinstance(other, SelectableInt):
+            assert other.bits == self.bits
+            other = other.value
+        if isinstance(other, int):
+            return other <= self.value
+        assert False
+
+    def __gt__(self, other):
+        if isinstance(other, SelectableInt):
+            assert other.bits == self.bits
+            other = other.value
+        if isinstance(other, int):
+            return other > self.value
+        assert False
+
+    def __lt__(self, other):
+        if isinstance(other, SelectableInt):
+            assert other.bits == self.bits
+            other = other.value
+        if isinstance(other, int):
+            return other < self.value
+        assert False
+
     def __eq__(self, other):
         if isinstance(other, SelectableInt):
-            return other.value == self.value and other.bits == self.bits
+            assert other.bits == self.bits
+            other = other.value
         if isinstance(other, int):
             return other == self.value
         assert False
@@ -100,6 +133,21 @@ class SelectableInt:
         return "SelectableInt(value={:x}, bits={})".format(self.value,
                                                            self.bits)
 
+def selectltu(lhs, rhs):
+    """ less-than (unsigned)
+    """
+    if isinstance(rhs, SelectableInt):
+        rhs = rhs.value
+    return lhs.value < rhs
+
+def selectgtu(lhs, rhs):
+    """ greater-than (unsigned)
+    """
+    if isinstance(rhs, SelectableInt):
+        rhs = rhs.value
+    return lhs.value > rhs
+
+
 # XXX this probably isn't needed...
 def selectassign(lhs, idx, rhs):
     if isinstance(idx, tuple):
@@ -153,7 +201,6 @@ class SelectableIntTestCase(unittest.TestCase):
         self.assertEqual(d.value, a.value | b.value)
         self.assertEqual(e.value, a.value ^ b.value)
         self.assertEqual(f.value, 0xF0)
-                          
 
     def test_get(self):
         a = SelectableInt(0xa2, 8)