Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear error message when using an Array as port #290

Closed
nmigen-issue-migration opened this issue Jan 1, 2020 · 0 comments
Closed

Unclear error message when using an Array as port #290

nmigen-issue-migration opened this issue Jan 1, 2020 · 0 comments
Milestone

Comments

@nmigen-issue-migration
Copy link

Issue by ZirconiumX
Wednesday Jan 01, 2020 at 18:25 GMT
Originally opened as m-labs/nmigen#290


When trying to use an Array as a port, nMigen yields the following traceback, which doesn't make it clear that Arrays are not permitted as Verilog ports.

Traceback (most recent call last):
  File "gpr.py", line 64, in <module>
    print(verilog.convert(dut, ports=ports))
  File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/back/verilog.py", line 76, in convert
    rtlil_text = rtlil.convert(*args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/back/rtlil.py", line 1010, in convert
    fragment = ir.Fragment.get(elaboratable, platform).prepare(**kwargs)
  File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/ir.py", line 556, in prepare
    fragment._propagate_ports(ports=(*ports, *new_ports), all_undef_as_ports=False)
  File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/xfrm.py", line 128, in on_value
    new_value = self.on_unknown_value(value)
  File "/usr/local/lib/python3.7/dist-packages/nmigen-0.2.dev13+g476ce15-py3.7.egg/nmigen/hdl/xfrm.py", line 86, in on_unknown_value
    raise TypeError("Cannot transform value {!r}".format(value)) # :nocov:
TypeError: Cannot transform value (array mutable [(array mutable [(sig $signal)]), (array mutable [(sig $signal)])])

Source used to generate this traceback:

from nmigen import *
from nmigen.back import rtlil, verilog


READ_PORTS_PER_CHANNEL  = 2
WRITE_PORTS_PER_CHANNEL = 1
CHANNELS                = 2
REGISTERS               = 32


class Gpr(Elaboratable):
    def __init__(self, rwidth=32):
        self.rwidth = rwidth
        self.rdepth = (REGISTERS - 1).bit_length()

        self.i_wr_a = Array(Array(Signal(self.rdepth) for _ in range(WRITE_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
        self.i_wr_d = Array(Array(Signal(rwidth) for _ in range(WRITE_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
        self.i_rd_a = Array(Array(Signal(self.rdepth) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))
        self.o_rd_d = Array(Array(Signal(rwidth) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))

    def elaborate(self, platform):
        m = Module()

        select  = Memory(width=CHANNELS, depth=self.rdepth)
        regfile = Array(Memory(width=self.rwidth, depth=self.rdepth) for _ in range(CHANNELS))
        readmux = Array(Array(Array(Signal(self.rwidth)) for _ in range(CHANNELS) for _ in range(READ_PORTS_PER_CHANNEL)) for _ in range(CHANNELS))

        for chan in range(CHANNELS):
            # Write ports
            for port in range(WRITE_PORTS_PER_CHANNEL):
                m.submodules["reg_write_c{}p{}".format(chan, port)] = reg_write_port = regfile[chan].write_port()
                m.submodules["sel_write_c{}p{}".format(chan, port)] = sel_write_port = select.write_port()
                m.d.comb += [
                    reg_write_port.addr.eq(self.i_wr_a[chan][port]),
                    reg_write_port.data.eq(self.i_wr_d[chan][port]),
                    sel_write_port.addr.eq(self.i_wr_a[chan][port]),
                    sel_write_port.data.eq(port)
                ]

            # Read ports
            for port in range(READ_PORTS_PER_CHANNEL):
                m.submodules["reg_read_c{}p{}".format(chan, port)] = reg_read_port = regfile[chan].read_port()
                m.submodules["sel_read_c{}p{}".format(chan, port)] = sel_read_port = select.read_port()

                for otherchan in range(CHANNELS):
                    m.d.comb += readmux[otherchan][port][chan].eq(reg_read_port.data)

                m.d.comb += [
                    reg_read_port.addr.eq(self.i_rd_a[chan][port]),
                    sel_read_port.addr.eq(self.i_rd_a[chan][port]),
                    self.o_rd_d[chan][port].eq(readmux[chan][port][sel_read_port.data])
                ]

        return m


dut = Gpr()

ports = [
    dut.i_wr_a, dut.i_wr_d,
    dut.i_rd_a, dut.o_rd_d
]

print(verilog.convert(dut, ports=ports))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

1 participant