lib.cdc: add diagnostic checks for synchronization stage count.
authorwhitequark <whitequark@whitequark.org>
Mon, 23 Sep 2019 19:38:21 +0000 (19:38 +0000)
committerwhitequark <whitequark@whitequark.org>
Mon, 23 Sep 2019 19:38:21 +0000 (19:38 +0000)
nmigen/lib/cdc.py
nmigen/test/test_lib_cdc.py

index c26b961b3ae3f757f234b9f61b62b3a1398baf8b..d21df79ae7d0609eca11f1117e694dbb806de626 100644 (file)
@@ -7,6 +7,14 @@ __all__ = ["FFSynchronizer", "ResetSynchronizer"]
 __all__ += ["MultiReg"]
 
 
+def _check_stages(stages):
+    if not isinstance(stages, int) or stages < 1:
+        raise TypeError("Synchronization stage count must be a positive integer, not '{!r}'"
+                        .format(stages))
+    if stages < 2:
+        raise ValueError("Synchronization stage count may not safely be less than 2")
+
+
 class FFSynchronizer(Elaboratable):
     """Resynchronise a signal to a different clock domain.
 
@@ -53,7 +61,9 @@ class FFSynchronizer(Elaboratable):
 
     :class:`FFSynchronizer` is reset by the ``o_domain`` reset only.
     """
-    def __init__(self, i, o, *, o_domain="sync", stages=2, reset=0, reset_less=True):
+    def __init__(self, i, o, *, o_domain="sync", reset=0, reset_less=True, stages=2):
+        _check_stages(stages)
+
         self.i = i
         self.o = o
 
@@ -108,6 +118,8 @@ class ResetSynchronizer(Elaboratable):
     :class:`ResetSynchronizer`, e.g. to instantiate library cells directly.
     """
     def __init__(self, arst, *, domain="sync", stages=2):
+        _check_stages(stages)
+
         self.arst = arst
 
         self._domain = domain
index 0d4894b466f3f89be8b84673b6fd92e1d43d6239..11785089056d8d3e62765a240fd01aa6f31b63cb 100644 (file)
@@ -5,6 +5,14 @@ from ..lib.cdc import *
 
 
 class FFSynchronizerTestCase(FHDLTestCase):
+    def test_stages_wrong(self):
+        with self.assertRaises(TypeError,
+                msg="Synchronization stage count must be a positive integer, not '0'"):
+            FFSynchronizer(Signal(), Signal(), stages=0)
+        with self.assertRaises(ValueError,
+                msg="Synchronization stage count may not safely be less than 2"):
+            FFSynchronizer(Signal(), Signal(), stages=1)
+
     def test_basic(self):
         i = Signal()
         o = Signal()
@@ -43,6 +51,14 @@ class FFSynchronizerTestCase(FHDLTestCase):
 
 
 class ResetSynchronizerTestCase(FHDLTestCase):
+    def test_stages_wrong(self):
+        with self.assertRaises(TypeError,
+                msg="Synchronization stage count must be a positive integer, not '0'"):
+            ResetSynchronizer(Signal(), stages=0)
+        with self.assertRaises(ValueError,
+                msg="Synchronization stage count may not safely be less than 2"):
+            ResetSynchronizer(Signal(), stages=1)
+
     def test_basic(self):
         arst = Signal()
         m = Module()