hdl.ast: experimentally add Value._as_const.
authorwhitequark <cz@m-labs.hk>
Tue, 1 Jan 2019 09:50:39 +0000 (09:50 +0000)
committerwhitequark <cz@m-labs.hk>
Tue, 1 Jan 2019 09:50:39 +0000 (09:50 +0000)
Useful for writing e.g. decoders that accept Cat, etc as argument.

nmigen/hdl/ast.py

index 7ee588d08d4b8cbd73c76838f74ad18ee04241a8..fc6a0de9dca19cc29d7c441db0ff76109d2d613c 100644 (file)
@@ -192,6 +192,9 @@ class Value(metaclass=ABCMeta):
     def _rhs_signals(self):
         pass # :nocov:
 
+    def _as_const(self):
+        raise TypeError("Value {!r} cannot be evaluated as constant".format(self))
+
     __hash__ = None
 
 
@@ -240,6 +243,9 @@ class Const(Value):
     def _rhs_signals(self):
         return ValueSet()
 
+    def _as_const(self):
+        return self.value
+
     def __repr__(self):
         return "(const {}'{}d{})".format(self.nbits, "s" if self.signed else "", self.value)
 
@@ -435,13 +441,20 @@ class Cat(Value):
         self.parts = [Value.wrap(v) for v in flatten(args)]
 
     def shape(self):
-        return sum(len(op) for op in self.parts), False
+        return sum(len(part) for part in self.parts), False
 
     def _lhs_signals(self):
-        return union(op._lhs_signals() for op in self.parts)
+        return union(part._lhs_signals() for part in self.parts)
 
     def _rhs_signals(self):
-        return union(op._rhs_signals() for op in self.parts)
+        return union(part._rhs_signals() for part in self.parts)
+
+    def _as_const(self):
+        value = 0
+        for part in reversed(self.parts):
+            value <<= len(part)
+            value |= part._as_const()
+        return value
 
     def __repr__(self):
         return "(cat {})".format(" ".join(map(repr, self.parts)))