vendor.fpga.lattice_ice40: instantiate SB_IO and apply extras.
authorwhitequark <cz@m-labs.hk>
Mon, 3 Jun 2019 02:48:55 +0000 (02:48 +0000)
committerwhitequark <cz@m-labs.hk>
Mon, 3 Jun 2019 02:51:59 +0000 (02:51 +0000)
The PULLUP and PULLUP_RESISTOR extras are representable in the PCF
file. The IO_STANDARD extra, however, can only be an SB_IO parameter.

nmigen/build/res.py
nmigen/test/test_build_res.py
nmigen/vendor/fpga/lattice_ice40.py

index 5ac3c64be95ff8373e11e6e073e20ecc79ccb5e6..9376f006764ba8e1c9b29917f87ae0db79d355f7 100644 (file)
@@ -111,10 +111,10 @@ class ConstraintManager:
                 phys = subsignal.io[0]
                 pin  = Pin(len(phys), dir, xdr, name=name)
                 if isinstance(phys, Pins):
-                    port = Signal(pin.width, name="{}_io".format(pin.name))
+                    port = Signal(pin.width, name="{}__io".format(pin.name))
                 if isinstance(phys, DiffPairs):
-                    port = (Signal(pin.width, name="{}_p".format(pin.name)),
-                            Signal(pin.width, name="{}_n".format(pin.name)))
+                    port = (Signal(pin.width, name="{}__p".format(pin.name)),
+                            Signal(pin.width, name="{}__n".format(pin.name)))
                 self._ports.append((subsignal, pin, port))
                 return pin
             else:
@@ -173,9 +173,9 @@ class ConstraintManager:
                                       "it has been requested as a tristate buffer"
                                       .format(name, number))
             if isinstance(resource.io[0], Pins):
-                port_name = "{}_io".format(pin.name)
+                port_name = "{}__io".format(pin.name)
             elif isinstance(resource.io[0], DiffPairs):
-                port_name = "{}_p".format(pin.name)
+                port_name = "{}__p".format(pin.name)
             else:
                 assert False
             yield (port_name, period)
index 26acc7c12e0136e94dec1d8a0c7687c4b67919e9..13b30423a130d3eb57ff3dc640cf1c9b2161c656 100644 (file)
@@ -66,7 +66,7 @@ class ConstraintManagerTestCase(FHDLTestCase):
         self.assertEqual(len(ports), 1)
 
         self.assertEqual(list(self.cm.iter_port_constraints()), [
-            ("user_led_0_io", ["A0"], {})
+            ("user_led_0__io", ["A0"], {})
         ])
 
     def test_request_with_dir(self):
@@ -82,7 +82,7 @@ class ConstraintManagerTestCase(FHDLTestCase):
         ports = list(self.cm.iter_ports())
         self.assertEqual(len(ports), 2)
         scl, sda = ports
-        self.assertEqual(ports[1].name, "i2c_0__sda_io")
+        self.assertEqual(ports[1].name, "i2c_0__sda__io")
         self.assertEqual(ports[1].nbits, 1)
 
         self.assertEqual(list(self.cm.iter_single_ended_pins()), [
@@ -90,8 +90,8 @@ class ConstraintManagerTestCase(FHDLTestCase):
             (i2c.sda, sda, {}),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints()), [
-            ("i2c_0__scl_io", ["N10"], {}),
-            ("i2c_0__sda_io", ["N11"], {})
+            ("i2c_0__scl__io", ["N10"], {}),
+            ("i2c_0__sda__io", ["N11"], {})
         ])
 
     def test_request_diffpairs(self):
@@ -103,23 +103,23 @@ class ConstraintManagerTestCase(FHDLTestCase):
         ports = list(self.cm.iter_ports())
         self.assertEqual(len(ports), 2)
         p, n = ports
-        self.assertEqual(p.name, "clk100_0_p")
+        self.assertEqual(p.name, "clk100_0__p")
         self.assertEqual(p.nbits, clk100.width)
-        self.assertEqual(n.name, "clk100_0_n")
+        self.assertEqual(n.name, "clk100_0__n")
         self.assertEqual(n.nbits, clk100.width)
 
         self.assertEqual(list(self.cm.iter_differential_pins()), [
             (clk100, p, n, {}),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints()), [
-            ("clk100_0_p", ["H1"], {}),
-            ("clk100_0_n", ["H2"], {}),
+            ("clk100_0__p", ["H1"], {}),
+            ("clk100_0__n", ["H2"], {}),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="p")), [
-            ("clk100_0_p", ["H1"], {}),
+            ("clk100_0__p", ["H1"], {}),
         ])
         self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="n")), [
-            ("clk100_0_n", ["H2"], {}),
+            ("clk100_0__n", ["H2"], {}),
         ])
 
     def test_add_clock(self):
@@ -130,8 +130,8 @@ class ConstraintManagerTestCase(FHDLTestCase):
         clk100 = self.cm.request("clk100", 0)
         clk50 = self.cm.request("clk50", 0, dir="i")
         self.assertEqual(list(sorted(self.cm.iter_clock_constraints())), [
-            ("clk100_0_p", 10e6),
-            ("clk50_0_io", 5e6)
+            ("clk100_0__p", 10e6),
+            ("clk50_0__io", 5e6)
         ])
 
     def test_wrong_resources(self):
index ab6c2a271f8119d60fb33f0b5bda1061afef8e18..9a8469c523e99e6595ecd45f84f10a107d06de2d 100644 (file)
@@ -3,6 +3,9 @@ import os
 import subprocess
 import tempfile
 
+from ...hdl.ast import *
+from ...hdl.dsl import *
+from ...hdl.ir import *
 from ...build import *
 
 
@@ -104,6 +107,38 @@ class LatticeICE40Platform(TemplatedPlatform):
         """
     ]
 
+    def _get_io_buffer(self, port, extras, fn):
+        m = Module()
+        for bit in range(len(port)):
+            m.submodules += Instance("SB_IO",
+                ("io", "PACKAGE_PIN", port[bit]),
+                *fn(bit),
+                *(("p", key, value) for key, value in extras.items()))
+        return m
+
+    def get_input(self, pin, port, extras):
+        return self._get_io_buffer(port, extras, lambda bit: [
+            # PIN_NO_OUTPUT|PIN_INPUT
+            ("p", "PIN_TYPE",       0b0000_01),
+            ("o", "D_IN_0",         pin.i[bit]),
+        ])
+
+    def get_output(self, pin, port, extras):
+        return self._get_io_buffer(port, extras, lambda bit: [
+            # PIN_OUTPUT|PIN_INPUT_REGISTERED
+            ("p", "PIN_TYPE",       0b0110_00),
+            ("i", "D_OUT_0",        pin.o[bit]),
+        ])
+
+    def get_tristate(self, pin, port, extras):
+        return self._get_io_buffer(port, extras, lambda bit: [
+            # PIN_OUTPUT_TRISTATE|PIN_INPUT_REGISTERED
+            ("p", "PIN_TYPE",       0b1010_00),
+            ("o", "D_IN_0",         pin.i[bit]),
+            ("i", "D_OUT_0",        pin.o[bit]),
+            ("i", "OUTPUT_ENABLE",  pin.oe),
+        ])
+
 
 class IceStormProgrammerMixin:
     def toolchain_program(self, products, name, *, mode=None):