add redirection of __Switch__ to allow overrides for advanced behaviour
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 27 Sep 2021 18:18:16 +0000 (19:18 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 27 Sep 2021 18:18:16 +0000 (19:18 +0100)
without changing fundamental language characteristics or semantics in nmigen
https://bugs.libre-soc.org/show_bug.cgi?id=458

nmigen/compat/fhdl/structure.py
nmigen/hdl/ast.py
nmigen/hdl/xfrm.py

index d450e4573b408cb4afd496ff13b0eae04d4213bd..68ddc497db424b28d40c1f9530af679575438202 100644 (file)
@@ -119,7 +119,7 @@ def choices(self):
     return self.elems
 
 
-class If(ast.Switch):
+class If(ast._InternalSwitch):
     @deprecated("instead of `If(cond, ...)`, use `with m.If(cond): ...`")
     def __init__(self, cond, *stmts):
         cond = Value.cast(cond)
@@ -143,7 +143,7 @@ class If(ast.Switch):
         return self
 
 
-class Case(ast.Switch):
+class Case(ast._InternalSwitch):
     @deprecated("instead of `Case(test, { value: stmts })`, use `with m.Switch(test):` and "
                 "`with m.Case(value): stmts`; instead of `\"default\": stmts`, use "
                 "`with m.Case(): stmts`")
index a2af8c744a772924b5489f78dbb83448b8a7e98d..d6944d23ae3627a6007f6a97824505a70cce3095 100644 (file)
@@ -15,6 +15,7 @@ __all__ = [
     "Shape", "signed", "unsigned",
     "Value", "Const", "C", "AnyConst", "AnySeq", "Operator", "Mux", "Part", "Slice", "Cat", "Repl",
     "Array", "ArrayProxy",
+    "_InternalSwitch",
     "Signal", "ClockSignal", "ResetSignal",
     "UserValue", "ValueCastable",
     "Sample", "Past", "Stable", "Rose", "Fell", "Initial",
@@ -153,6 +154,11 @@ class Value(metaclass=ABCMeta):
     def __Mux__(self, val1, val0):
         return _InternalMux(self, val1, val0)
 
+    def __Switch__(self, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
+        return _InternalSwitch(self, cases, src_loc=src_loc,
+                               src_loc_at=src_loc_at,
+                               case_src_locs=case_src_locs)
+
     def __bool__(self):
         raise TypeError("Attempted to convert nMigen value to Python boolean")
 
@@ -1485,7 +1491,12 @@ class Cover(Property):
 
 
 # @final
-class Switch(Statement):
+def Switch(test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
+    return test.__Switch__(cases, src_loc=src_loc, src_loc_at=src_loc_at,
+                           case_src_locs=case_src_locs)
+
+
+class _InternalSwitch(Statement):
     def __init__(self, test, cases, *, src_loc=None, src_loc_at=0, case_src_locs={}):
         if src_loc is None:
             super().__init__(src_loc_at=src_loc_at)
index 97f8c5312c61f36976bf146ab35786bae7e6ec9b..7cf142ad9d6d934c253a0fc910f407858260e462 100644 (file)
@@ -213,7 +213,7 @@ class StatementVisitor(metaclass=ABCMeta):
             new_stmt = self.on_Assume(stmt)
         elif type(stmt) is Cover:
             new_stmt = self.on_Cover(stmt)
-        elif isinstance(stmt, Switch):
+        elif isinstance(stmt, _InternalSwitch):
             # Uses `isinstance()` and not `type() is` because nmigen.compat requires it.
             new_stmt = self.on_Switch(stmt)
         elif isinstance(stmt, Iterable):
@@ -222,7 +222,8 @@ class StatementVisitor(metaclass=ABCMeta):
             new_stmt = self.on_unknown_statement(stmt)
         if isinstance(new_stmt, Statement) and self.replace_statement_src_loc(stmt, new_stmt):
             new_stmt.src_loc = stmt.src_loc
-            if isinstance(new_stmt, Switch) and isinstance(stmt, Switch):
+            if (isinstance(new_stmt, _InternalSwitch) and
+                isinstance(stmt, _InternalSwitch)):
                 new_stmt.case_src_locs = stmt.case_src_locs
         if isinstance(new_stmt, Property):
             new_stmt._MustUse__used = True