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

Cast reset value for transparent read ports to integer #454

Merged
merged 1 commit into from
Jul 30, 2020
Merged

Cast reset value for transparent read ports to integer #454

merged 1 commit into from
Jul 30, 2020

Conversation

adamgreig
Copy link
Contributor

Currently if you pass a list of items which can be converted to an integer but are not integers (for example, numpy.int64 objects), they are converted when used to initialise Memory._array, but a transparent read port sets its reset value to mem.init[0], which is not cast.

This eventually causes VcdWriter to bomb out because it checks isinstance(value, int) which fails for numpy.int64.

This PR uses operator.index to cast the value to an integer, the same way it's done inside the init setter when creating Memory._array.

Test case:

import numpy as np
import nmigen as nm
from nmigen.back import pysim


class Foo(nm.Elaboratable):
    def __init__(self):
        self.idx = nm.Signal(7)
        self.out = nm.Signal(8)

    def elaborate(self, platform):
        data = np.arange(128, dtype=np.int)
        mem = nm.Memory(width=8, depth=128, init=data)
        print(type(mem._array[0].reset))
        m = nm.Module()
        # Change to transparent=False to avoid use of Mem.init[0]
        rp = mem.read_port(transparent=True)
        m.submodules += rp
        m.d.sync += rp.addr.eq(self.idx), self.out.eq(rp.data)
        return m


mod = Foo()


def testbench():
    yield
    for i in range(10):
        yield mod.idx.eq(i)
        yield
        print((yield mod.out))
        yield


sim = pysim.Simulator(mod)
sim.add_clock(1e-6)
sim.add_sync_process(testbench)
with sim.write_vcd("test.vcd"):
    sim.run()

Traceback:

Traceback (most recent call last):
  File "test.py", line 37, in <module>
    with sim.write_vcd("test.vcd"):
  File "/home/adam/.local/lib/python3.6/site-packages/nmigen-0.3.dev63+gd90f0fe-py3.6.egg/nmigen/back/pysim.py", line 1124, in write_vcd
    vcd_file=vcd_file, gtkw_file=gtkw_file, traces=traces)
  File "/home/adam/.local/lib/python3.6/site-packages/nmigen-0.3.dev63+gd90f0fe-py3.6.egg/nmigen/back/pysim.py", line 124, in __init__
    var_type=var_type, size=var_size, init=var_init)
  File "/home/adam/.local/lib/python3.6/site-packages/vcd/writer.py", line 282, in register_var
    raise ValueError('vector init value must be int, bool, str, or None')
ValueError: vector init value must be int, bool, str, or None

@adamgreig
Copy link
Contributor Author

Alternatively we could use

            if len(self.memory._array) > 0:
                self.data.reset = self.memory._array[0].reset

rather than doing the cast again (although it should succeed, since a failure would have been caught the first time).

@whitequark whitequark merged commit 07dc163 into amaranth-lang:master Jul 30, 2020
@whitequark
Copy link
Member

Thanks!

@adamgreig adamgreig deleted the cast-mem-init-reset-value branch July 30, 2020 21:05
@adamgreig adamgreig restored the cast-mem-init-reset-value branch July 30, 2020 21:05
@adamgreig adamgreig deleted the cast-mem-init-reset-value branch July 30, 2020 21:05
@adamgreig adamgreig restored the cast-mem-init-reset-value branch July 30, 2020 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants