build.res: allow querying frequency of a previously constrained clock.
authorwhitequark <whitequark@whitequark.org>
Wed, 5 Jun 2019 12:51:53 +0000 (12:51 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 5 Jun 2019 12:51:53 +0000 (12:51 +0000)
nmigen/build/res.py
nmigen/test/test_build_res.py

index 70677986702299ef78ae0a92986198bf43e9b930..29926028b35309600383805c9cb9cfcbbc03e2c7 100644 (file)
@@ -191,11 +191,9 @@ class ResourceManager:
                 for bit, pin_name in enumerate(pin_names):
                     yield "{}[{}]".format(port_name, bit), pin_name, attrs
 
-    def add_clock_constraint(self, clock, frequency):
+    def _map_clock_to_port(self, clock):
         if not isinstance(clock, (Signal, Pin)):
             raise TypeError("Object {!r} is not a Signal or Pin".format(clock))
-        if not isinstance(frequency, (int, float)):
-            raise TypeError("Frequency must be a number, not {!r}".format(frequency))
 
         if isinstance(clock, Pin):
             for res, pin, port, attrs in self._ports:
@@ -208,16 +206,27 @@ class ResourceManager:
                         assert False
                     break
             else:
-                raise ValueError("Cannot add clock constraint on a Pin {!r} that is not "
-                                 "a previously requested resource"
+                raise ValueError("The Pin object {!r}, which is not a previously requested "
+                                 "resource, cannot be used to desigate a clock"
                                  .format(clock))
 
+        return clock
+
+    def add_clock_constraint(self, clock, frequency):
+        if not isinstance(frequency, (int, float)):
+            raise TypeError("Frequency must be a number, not {!r}".format(frequency))
+
+        clock = self._map_clock_to_port(clock)
         if clock in self._clocks:
             raise ValueError("Cannot add clock constraint on {!r}, which is already constrained "
                              "to {} Hz"
                              .format(clock, self._clocks[clock]))
+        else:
+            self._clocks[clock] = float(frequency)
 
-        self._clocks[clock] = float(frequency)
+    def get_clock_constraint(self, clock):
+        clock = self._map_clock_to_port(clock)
+        return self._clocks[clock]
 
     def iter_clock_constraints(self):
         return iter(self._clocks.items())
index d4efef3342e46eeedc9e88c26247c26014a36c3c..a221cd4992bc6f25bec8e3c0691bd1e5dd88f10a 100644 (file)
@@ -168,6 +168,12 @@ class ResourceManagerTestCase(FHDLTestCase):
             (scl_port, 100e3)
         ])
 
+    def test_get_clock(self):
+        clk100 = self.cm.request("clk100", 0)
+        self.assertEqual(self.cm.get_clock_constraint(clk100), 100e6)
+        with self.assertRaises(KeyError):
+            self.cm.get_clock_constraint(Signal())
+
     def test_wrong_resources(self):
         with self.assertRaises(TypeError, msg="Object 'wrong' is not a Resource"):
             self.cm.add_resources(['wrong'])
@@ -203,6 +209,12 @@ class ResourceManagerTestCase(FHDLTestCase):
                 msg="Frequency must be a number, not None"):
             self.cm.add_clock_constraint(Signal(), None)
 
+    def test_wrong_clock_pin(self):
+        with self.assertRaises(ValueError,
+                msg="The Pin object (rec <unnamed> i), which is not a previously requested "
+                    "resource, cannot be used to desigate a clock"):
+            self.cm.add_clock_constraint(Pin(1, dir="i"), 1e6)
+
     def test_wrong_request_duplicate(self):
         with self.assertRaises(ResourceError,
                 msg="Resource user_led#0 has already been requested"):