2021-12-09 22:39:50 -07:00
|
|
|
# amaranth: UnusedElaboratable=no
|
2019-10-26 00:36:54 -06:00
|
|
|
|
2024-01-30 09:43:33 -07:00
|
|
|
from amaranth.hdl._ast import *
|
|
|
|
from amaranth.hdl._mem import *
|
2024-02-14 03:27:39 -07:00
|
|
|
from amaranth._utils import _ignore_deprecated
|
tests: move out of the main package.
Compared to tests in the repository root, tests in the package have
many downsides:
* Unless explicitly excluded in find_packages(), tests and their
support code effectively become a part of public API.
This, unfortunately, happened with FHDLTestCase, which was never
intended for downstream use.
* Even if explicitly excluded from the setuptools package, using
an editable install, or setting PYTHONPATH still allows accessing
the tests.
* Having a sub-package that is present in the source tree but not
exported (or, worse, exported only sometimes) is confusing.
* The name `nmigen.test` cannot be used for anything else, such as
testing utilities that *are* intended for downstream use.
2020-08-26 18:33:31 -06:00
|
|
|
|
2019-10-13 12:53:38 -06:00
|
|
|
from .utils import *
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
|
|
|
|
class MemoryTestCase(FHDLTestCase):
|
|
|
|
def test_name(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
m1 = Memory(width=8, depth=4)
|
|
|
|
self.assertEqual(m1.name, "m1")
|
|
|
|
m2 = [Memory(width=8, depth=4)][0]
|
|
|
|
self.assertEqual(m2.name, "$memory")
|
|
|
|
m3 = Memory(width=8, depth=4, name="foo")
|
|
|
|
self.assertEqual(m3.name, "foo")
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_geometry(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
m = Memory(width=8, depth=4)
|
|
|
|
self.assertEqual(m.width, 8)
|
|
|
|
self.assertEqual(m.depth, 4)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_geometry_wrong(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
with self.assertRaisesRegex(TypeError,
|
|
|
|
r"^Memory width must be a non-negative integer, not -1$"):
|
|
|
|
m = Memory(width=-1, depth=4)
|
|
|
|
with self.assertRaisesRegex(TypeError,
|
|
|
|
r"^Memory depth must be a non-negative integer, not -1$"):
|
|
|
|
m = Memory(width=8, depth=-1)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_init(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
m = Memory(width=8, depth=4, init=range(4))
|
|
|
|
self.assertEqual(m.init, [0, 1, 2, 3])
|
2018-12-20 23:07:16 -07:00
|
|
|
|
2019-06-10 21:38:44 -06:00
|
|
|
def test_init_wrong_count(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
with self.assertRaisesRegex(ValueError,
|
|
|
|
r"^Memory initialization value count exceed memory depth \(8 > 4\)$"):
|
|
|
|
m = Memory(width=8, depth=4, init=range(8))
|
2018-12-20 23:07:16 -07:00
|
|
|
|
2019-06-10 21:38:44 -06:00
|
|
|
def test_init_wrong_type(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
with self.assertRaisesRegex(TypeError,
|
|
|
|
(r"^Memory initialization value at address 1: "
|
|
|
|
r"'str' object cannot be interpreted as an integer$")):
|
|
|
|
m = Memory(width=8, depth=4, init=[1, "0"])
|
2019-06-10 21:38:44 -06:00
|
|
|
|
2020-02-06 07:48:48 -07:00
|
|
|
def test_attrs(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
m1 = Memory(width=8, depth=4)
|
|
|
|
self.assertEqual(m1.attrs, {})
|
|
|
|
m2 = Memory(width=8, depth=4, attrs={"ram_block": True})
|
|
|
|
self.assertEqual(m2.attrs, {"ram_block": True})
|
2020-02-06 07:48:48 -07:00
|
|
|
|
2018-12-20 23:07:16 -07:00
|
|
|
def test_read_port_transparent(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
rdport = mem.read_port()
|
|
|
|
self.assertEqual(rdport.memory, mem)
|
|
|
|
self.assertEqual(rdport.domain, "sync")
|
|
|
|
self.assertEqual(rdport.transparent, True)
|
|
|
|
self.assertEqual(len(rdport.addr), 2)
|
|
|
|
self.assertEqual(len(rdport.data), 8)
|
|
|
|
self.assertEqual(len(rdport.en), 1)
|
|
|
|
self.assertIsInstance(rdport.en, Signal)
|
|
|
|
self.assertEqual(rdport.en.init, 1)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_read_port_non_transparent(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
rdport = mem.read_port(transparent=False)
|
|
|
|
self.assertEqual(rdport.memory, mem)
|
|
|
|
self.assertEqual(rdport.domain, "sync")
|
|
|
|
self.assertEqual(rdport.transparent, False)
|
|
|
|
self.assertEqual(len(rdport.en), 1)
|
|
|
|
self.assertIsInstance(rdport.en, Signal)
|
|
|
|
self.assertEqual(rdport.en.init, 1)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_read_port_asynchronous(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
rdport = mem.read_port(domain="comb")
|
|
|
|
self.assertEqual(rdport.memory, mem)
|
|
|
|
self.assertEqual(rdport.domain, "comb")
|
|
|
|
self.assertEqual(rdport.transparent, True)
|
|
|
|
self.assertEqual(len(rdport.en), 1)
|
|
|
|
self.assertIsInstance(rdport.en, Const)
|
|
|
|
self.assertEqual(rdport.en.value, 1)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_read_port_wrong(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
with self.assertRaisesRegex(ValueError,
|
|
|
|
r"^Read port cannot be simultaneously asynchronous and non-transparent$"):
|
|
|
|
mem.read_port(domain="comb", transparent=False)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_write_port(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
wrport = mem.write_port()
|
|
|
|
self.assertEqual(wrport.memory, mem)
|
|
|
|
self.assertEqual(wrport.domain, "sync")
|
|
|
|
self.assertEqual(wrport.granularity, 8)
|
|
|
|
self.assertEqual(len(wrport.addr), 2)
|
|
|
|
self.assertEqual(len(wrport.data), 8)
|
|
|
|
self.assertEqual(len(wrport.en), 1)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_write_port_granularity(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
wrport = mem.write_port(granularity=2)
|
|
|
|
self.assertEqual(wrport.memory, mem)
|
|
|
|
self.assertEqual(wrport.domain, "sync")
|
|
|
|
self.assertEqual(wrport.granularity, 2)
|
|
|
|
self.assertEqual(len(wrport.addr), 2)
|
|
|
|
self.assertEqual(len(wrport.data), 8)
|
|
|
|
self.assertEqual(len(wrport.en), 4)
|
2018-12-20 23:07:16 -07:00
|
|
|
|
|
|
|
def test_write_port_granularity_wrong(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
mem = Memory(width=8, depth=4)
|
2020-07-28 13:35:25 -06:00
|
|
|
with self.assertRaisesRegex(TypeError,
|
|
|
|
r"^Write port granularity must be a non-negative integer, not -1$"):
|
2018-12-20 23:07:16 -07:00
|
|
|
mem.write_port(granularity=-1)
|
2020-07-28 13:35:25 -06:00
|
|
|
with self.assertRaisesRegex(ValueError,
|
|
|
|
r"^Write port granularity must not be greater than memory width \(10 > 8\)$"):
|
2018-12-20 23:07:16 -07:00
|
|
|
mem.write_port(granularity=10)
|
2020-07-28 13:35:25 -06:00
|
|
|
with self.assertRaisesRegex(ValueError,
|
|
|
|
r"^Write port granularity must divide memory width evenly$"):
|
2018-12-20 23:07:16 -07:00
|
|
|
mem.write_port(granularity=3)
|
2018-12-31 20:08:10 -07:00
|
|
|
|
2024-02-14 03:27:39 -07:00
|
|
|
def test_deprecated(self):
|
|
|
|
with self.assertWarnsRegex(DeprecationWarning,
|
|
|
|
r"^`amaranth.hdl.Memory` is deprecated.*$"):
|
|
|
|
mem = Memory(width=8, depth=4)
|
|
|
|
|
2018-12-31 20:08:10 -07:00
|
|
|
|
|
|
|
class DummyPortTestCase(FHDLTestCase):
|
|
|
|
def test_name(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
p1 = DummyPort(data_width=8, addr_width=2)
|
|
|
|
self.assertEqual(p1.addr.name, "p1_addr")
|
|
|
|
p2 = [DummyPort(data_width=8, addr_width=2)][0]
|
|
|
|
self.assertEqual(p2.addr.name, "dummy_addr")
|
|
|
|
p3 = DummyPort(data_width=8, addr_width=2, name="foo")
|
|
|
|
self.assertEqual(p3.addr.name, "foo_addr")
|
2018-12-31 20:08:10 -07:00
|
|
|
|
|
|
|
def test_sizes(self):
|
2024-02-14 03:27:39 -07:00
|
|
|
with _ignore_deprecated():
|
|
|
|
p1 = DummyPort(data_width=8, addr_width=2)
|
|
|
|
self.assertEqual(p1.addr.width, 2)
|
|
|
|
self.assertEqual(p1.data.width, 8)
|
|
|
|
self.assertEqual(p1.en.width, 1)
|
|
|
|
p2 = DummyPort(data_width=8, addr_width=2, granularity=2)
|
|
|
|
self.assertEqual(p2.en.width, 4)
|
|
|
|
|
|
|
|
def test_deprecated(self):
|
|
|
|
with self.assertWarnsRegex(DeprecationWarning,
|
|
|
|
r"^`DummyPort` is deprecated.*$"):
|
|
|
|
DummyPort(data_width=8, addr_width=2)
|