Fixed GPIO block issue that accessed out of bounds Array()
authorAndrey Miroshnikov <andrey@technepisteme.xyz>
Mon, 21 Mar 2022 00:03:58 +0000 (00:03 +0000)
committerAndrey Miroshnikov <andrey@technepisteme.xyz>
Mon, 21 Mar 2022 00:03:58 +0000 (00:03 +0000)
src/spec/pinmux.py
src/spec/simple_gpio.py

index 0b0039d6b3a06a5b5afe43f95c46ca702b2b6bdf..93bb974bcc1deb1ae13faac6aba7368ee2ba4d1a 100644 (file)
@@ -203,7 +203,9 @@ def test_gpio_pinmux(dut):
     yield dut.periph_ports[0].o.eq(1)
     yield dut.periph_ports[0].oe.eq(1)
     yield dut.pad_port.i.eq(1)
-
+    yield
+    yield from gpios.config("0", oe=0, ie=0, puen=0, pden=1, outval=0, bank=0)
+    yield from gpios.rd_input("0")
 
     print("Finished the 1-bit IO mux block test!")
 
index 506675b6cab3712b0a768ac30c7f9fcbc286d69d..57cfeffa3503f80ac5526ab75d4199fdd28371be 100644 (file)
@@ -7,7 +7,7 @@ Modified for use with pinmux, will probably change the class name later.
 """
 from random import randint
 from math import ceil, floor
-from nmigen import Elaboratable, Module, Signal, Record, Array, Cat
+from nmigen import Elaboratable, Module, Signal, Record, Array, Cat, Const
 from nmigen.hdl.rec import Layout
 from nmigen.utils import log2_int
 from nmigen.cli import rtlil
@@ -84,7 +84,12 @@ class SimpleGPIO(Elaboratable):
 
         comb += wb_ack.eq(0)
 
-        row_start = Signal(log2_int(self.n_gpio))
+        # log2_int(1) will give 0, which wouldn't work?
+        if (self.n_gpio == 1):
+            row_start = Signal(1)
+        else:
+            row_start = Signal(log2_int(self.n_gpio))
+
         # Flag for indicating rd/wr transactions
         new_transaction = Signal(1)
 
@@ -110,25 +115,41 @@ class SimpleGPIO(Elaboratable):
                 comb += wb_rd_data.eq(Cat(multi_cat))
         with m.Else():
             sync += new_transaction.eq(0)
-            # Update the state of "io" while no WB transactions
-            for byte in range(0, self.wordsize):
-                with m.If(gpio_ports[row_start+byte].oe):
-                    sync += multi[byte].io.eq(gpio_ports[row_start+byte].o)
-                with m.Else():
-                    sync += multi[byte].io.eq(gpio_ports[row_start+byte].i)
+
         # Only update GPIOs config if a new transaction happened last cycle
         # (read or write). Always lags from multi csrbus by 1 clk cycle, most
         # sane way I could think of while using Record().
         with m.If(new_transaction):
-            for byte in range(0, self.wordsize):
-                sync += gpio_ports[row_start+byte].oe.eq(multi[byte].oe)
-                sync += gpio_ports[row_start+byte].puen.eq(multi[byte].puen)
-                sync += gpio_ports[row_start+byte].pden.eq(multi[byte].pden)
-                # Check to prevent output being set if GPIO configured as input
-                # TODO: No checking is done if ie/oe high together
-                with m.If(gpio_ports[row_start+byte].oe):
-                    sync += gpio_ports[row_start+byte].o.eq(multi[byte].io)
-                sync += gpio_ports[row_start+byte].bank.eq(multi[byte].bank)
+            # This is a complex case, not needed atm
+            if self.n_gpio > self.wordsize:
+                print("NOT IMPLEMENTED THIS CASE")
+                """
+                for byte in range(0, self.wordsize):
+                    if ((row_start+byte) < Const(self.n_gpio)):
+                        sync += gpio_ports[row+byte].oe.eq(multi[byte].oe)
+                        sync += gpio_ports[row+byte].puen.eq(multi[byte].puen)
+                        sync += gpio_ports[row+byte].pden.eq(multi[byte].pden)
+                        # prevent output being set if GPIO configured as i
+                        # TODO: No checking is done if ie/oe high together
+                        with m.If(gpio_ports[row+byte].oe):
+                            sync += gpio_ports[row+byte].o.eq(multi[byte].io)
+                        with m.Else():
+                            sync += multi[byte].io.eq(gpio_ports[row+byte].i)
+                        sync += gpio_ports[row+byte].bank.eq(multi[byte].bank)
+                """
+                raise
+            else:
+                for byte in range(self.n_gpio):
+                    sync += gpio_ports[byte].oe.eq(multi[byte].oe)
+                    sync += gpio_ports[byte].puen.eq(multi[byte].puen)
+                    sync += gpio_ports[byte].pden.eq(multi[byte].pden)
+                    # Check to prevent output being set if GPIO configured as i
+                    # TODO: No checking is done if ie/oe high together
+                    with m.If(multi[byte].oe): # gpio_ports[byte].oe):
+                        sync += gpio_ports[byte].o.eq(multi[byte].io)
+                    with m.Else():
+                        sync += multi[byte].io.eq(gpio_ports[byte].i)
+                    sync += gpio_ports[byte].bank.eq(multi[byte].bank)
         return m
 
     def __iter__(self):