tests: Exorcise some star-imports.

This commit is contained in:
Wanda 2024-03-13 18:54:42 +01:00 committed by Catherine
parent 27ca96383e
commit 49dee891e8
2 changed files with 281 additions and 283 deletions

View file

@ -3,8 +3,7 @@ import operator
from unittest import TestCase from unittest import TestCase
from amaranth.hdl import * from amaranth.hdl import *
from amaranth.hdl._ast import ShapeCastable from amaranth.lib import data
from amaranth.lib.data import *
from amaranth.sim import Simulator from amaranth.sim import Simulator
from .utils import * from .utils import *
@ -26,56 +25,56 @@ class MockShapeCastable(ShapeCastable):
class FieldTestCase(TestCase): class FieldTestCase(TestCase):
def test_construct(self): def test_construct(self):
f = Field(unsigned(2), 1) f = data.Field(unsigned(2), 1)
self.assertEqual(f.shape, unsigned(2)) self.assertEqual(f.shape, unsigned(2))
self.assertEqual(f.offset, 1) self.assertEqual(f.offset, 1)
self.assertEqual(f.width, 2) self.assertEqual(f.width, 2)
def test_repr(self): def test_repr(self):
f = Field(unsigned(2), 1) f = data.Field(unsigned(2), 1)
self.assertEqual(repr(f), "Field(unsigned(2), 1)") self.assertEqual(repr(f), "Field(unsigned(2), 1)")
def test_equal(self): def test_equal(self):
f1 = Field(unsigned(2), 1) f1 = data.Field(unsigned(2), 1)
f2 = Field(unsigned(2), 0) f2 = data.Field(unsigned(2), 0)
self.assertNotEqual(f1, f2) self.assertNotEqual(f1, f2)
f3 = Field(unsigned(2), 1) f3 = data.Field(unsigned(2), 1)
self.assertEqual(f1, f3) self.assertEqual(f1, f3)
f4 = Field(2, 1) f4 = data.Field(2, 1)
self.assertEqual(f1, f4) self.assertEqual(f1, f4)
f5 = Field(MockShapeCastable(unsigned(2)), 1) f5 = data.Field(MockShapeCastable(unsigned(2)), 1)
self.assertEqual(f1, f5) self.assertEqual(f1, f5)
self.assertNotEqual(f1, object()) self.assertNotEqual(f1, object())
def test_preserve_shape(self): def test_preserve_shape(self):
sc = MockShapeCastable(unsigned(2)) sc = MockShapeCastable(unsigned(2))
f = Field(sc, 0) f = data.Field(sc, 0)
self.assertEqual(f.shape, sc) self.assertEqual(f.shape, sc)
self.assertEqual(f.width, 2) self.assertEqual(f.width, 2)
def test_shape_wrong(self): def test_shape_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Field shape must be a shape-castable object, not <.+>$"): r"^Field shape must be a shape-castable object, not <.+>$"):
Field(object(), 0) data.Field(object(), 0)
def test_offset_wrong(self): def test_offset_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Field offset must be a non-negative integer, not <.+>$"): r"^Field offset must be a non-negative integer, not <.+>$"):
Field(unsigned(2), object()) data.Field(unsigned(2), object())
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Field offset must be a non-negative integer, not -1$"): r"^Field offset must be a non-negative integer, not -1$"):
Field(unsigned(2), -1) data.Field(unsigned(2), -1)
def test_immutable(self): def test_immutable(self):
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
Field(1, 0).shape = unsigned(2) data.Field(1, 0).shape = unsigned(2)
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
Field(1, 0).offset = 1 data.Field(1, 0).offset = 1
class StructLayoutTestCase(TestCase): class StructLayoutTestCase(TestCase):
def test_construct(self): def test_construct(self):
sl = StructLayout({ sl = data.StructLayout({
"a": unsigned(1), "a": unsigned(1),
"b": 2 "b": 2
}) })
@ -85,25 +84,25 @@ class StructLayoutTestCase(TestCase):
}) })
self.assertEqual(sl.size, 3) self.assertEqual(sl.size, 3)
self.assertEqual(list(iter(sl)), [ self.assertEqual(list(iter(sl)), [
("a", Field(unsigned(1), 0)), ("a", data.Field(unsigned(1), 0)),
("b", Field(2, 1)) ("b", data.Field(2, 1))
]) ])
self.assertEqual(sl["a"], Field(unsigned(1), 0)) self.assertEqual(sl["a"], data.Field(unsigned(1), 0))
self.assertEqual(sl["b"], Field(2, 1)) self.assertEqual(sl["b"], data.Field(2, 1))
def test_size_empty(self): def test_size_empty(self):
self.assertEqual(StructLayout({}).size, 0) self.assertEqual(data.StructLayout({}).size, 0)
def test_eq(self): def test_eq(self):
self.assertEqual(StructLayout({"a": unsigned(1), "b": 2}), self.assertEqual(data.StructLayout({"a": unsigned(1), "b": 2}),
StructLayout({"a": unsigned(1), "b": unsigned(2)})) data.StructLayout({"a": unsigned(1), "b": unsigned(2)}))
self.assertNotEqual(StructLayout({"a": unsigned(1), "b": 2}), self.assertNotEqual(data.StructLayout({"a": unsigned(1), "b": 2}),
StructLayout({"b": unsigned(2), "a": unsigned(1)})) data.StructLayout({"b": unsigned(2), "a": unsigned(1)}))
self.assertNotEqual(StructLayout({"a": unsigned(1), "b": 2}), self.assertNotEqual(data.StructLayout({"a": unsigned(1), "b": 2}),
StructLayout({"a": unsigned(1)})) data.StructLayout({"a": unsigned(1)}))
def test_repr(self): def test_repr(self):
sl = StructLayout({ sl = data.StructLayout({
"a": unsigned(1), "a": unsigned(1),
"b": 2 "b": 2
}) })
@ -112,22 +111,22 @@ class StructLayoutTestCase(TestCase):
def test_members_wrong(self): def test_members_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Struct layout members must be provided as a mapping, not <.+>$"): r"^Struct layout members must be provided as a mapping, not <.+>$"):
StructLayout(object()) data.StructLayout(object())
def test_member_key_wrong(self): def test_member_key_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Struct layout member name must be a string, not 1\.0$"): r"^Struct layout member name must be a string, not 1\.0$"):
StructLayout({1.0: unsigned(1)}) data.StructLayout({1.0: unsigned(1)})
def test_member_value_wrong(self): def test_member_value_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Struct layout member shape must be a shape-castable object, not 1\.0$"): r"^Struct layout member shape must be a shape-castable object, not 1\.0$"):
StructLayout({"a": 1.0}) data.StructLayout({"a": 1.0})
class UnionLayoutTestCase(TestCase): class UnionLayoutTestCase(TestCase):
def test_construct(self): def test_construct(self):
ul = UnionLayout({ ul = data.UnionLayout({
"a": unsigned(1), "a": unsigned(1),
"b": 2 "b": 2
}) })
@ -137,25 +136,25 @@ class UnionLayoutTestCase(TestCase):
}) })
self.assertEqual(ul.size, 2) self.assertEqual(ul.size, 2)
self.assertEqual(list(iter(ul)), [ self.assertEqual(list(iter(ul)), [
("a", Field(unsigned(1), 0)), ("a", data.Field(unsigned(1), 0)),
("b", Field(2, 0)) ("b", data.Field(2, 0))
]) ])
self.assertEqual(ul["a"], Field(unsigned(1), 0)) self.assertEqual(ul["a"], data.Field(unsigned(1), 0))
self.assertEqual(ul["b"], Field(2, 0)) self.assertEqual(ul["b"], data.Field(2, 0))
def test_size_empty(self): def test_size_empty(self):
self.assertEqual(UnionLayout({}).size, 0) self.assertEqual(data.UnionLayout({}).size, 0)
def test_eq(self): def test_eq(self):
self.assertEqual(UnionLayout({"a": unsigned(1), "b": 2}), self.assertEqual(data.UnionLayout({"a": unsigned(1), "b": 2}),
UnionLayout({"a": unsigned(1), "b": unsigned(2)})) data.UnionLayout({"a": unsigned(1), "b": unsigned(2)}))
self.assertEqual(UnionLayout({"a": unsigned(1), "b": 2}), self.assertEqual(data.UnionLayout({"a": unsigned(1), "b": 2}),
UnionLayout({"b": unsigned(2), "a": unsigned(1)})) data.UnionLayout({"b": unsigned(2), "a": unsigned(1)}))
self.assertNotEqual(UnionLayout({"a": unsigned(1), "b": 2}), self.assertNotEqual(data.UnionLayout({"a": unsigned(1), "b": 2}),
UnionLayout({"a": unsigned(1)})) data.UnionLayout({"a": unsigned(1)}))
def test_repr(self): def test_repr(self):
ul = UnionLayout({ ul = data.UnionLayout({
"a": unsigned(1), "a": unsigned(1),
"b": 2 "b": 2
}) })
@ -164,79 +163,79 @@ class UnionLayoutTestCase(TestCase):
def test_members_wrong(self): def test_members_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Union layout members must be provided as a mapping, not <.+>$"): r"^Union layout members must be provided as a mapping, not <.+>$"):
UnionLayout(object()) data.UnionLayout(object())
def test_member_key_wrong(self): def test_member_key_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Union layout member name must be a string, not 1\.0$"): r"^Union layout member name must be a string, not 1\.0$"):
UnionLayout({1.0: unsigned(1)}) data.UnionLayout({1.0: unsigned(1)})
def test_member_value_wrong(self): def test_member_value_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Union layout member shape must be a shape-castable object, not 1\.0$"): r"^Union layout member shape must be a shape-castable object, not 1\.0$"):
UnionLayout({"a": 1.0}) data.UnionLayout({"a": 1.0})
def test_const_two_members_wrong(self): def test_const_two_members_wrong(self):
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Initializer for at most one field can be provided for a union layout " r"^Initializer for at most one field can be provided for a union layout "
r"\(specified: a, b\)$"): r"\(specified: a, b\)$"):
UnionLayout({"a": 1, "b": 2}).const(dict(a=1, b=2)) data.UnionLayout({"a": 1, "b": 2}).const(dict(a=1, b=2))
class ArrayLayoutTestCase(TestCase): class ArrayLayoutTestCase(TestCase):
def test_construct(self): def test_construct(self):
al = ArrayLayout(unsigned(2), 3) al = data.ArrayLayout(unsigned(2), 3)
self.assertEqual(al.elem_shape, unsigned(2)) self.assertEqual(al.elem_shape, unsigned(2))
self.assertEqual(al.length, 3) self.assertEqual(al.length, 3)
self.assertEqual(list(iter(al)), [ self.assertEqual(list(iter(al)), [
(0, Field(unsigned(2), 0)), (0, data.Field(unsigned(2), 0)),
(1, Field(unsigned(2), 2)), (1, data.Field(unsigned(2), 2)),
(2, Field(unsigned(2), 4)), (2, data.Field(unsigned(2), 4)),
]) ])
self.assertEqual(al[0], Field(unsigned(2), 0)) self.assertEqual(al[0], data.Field(unsigned(2), 0))
self.assertEqual(al[1], Field(unsigned(2), 2)) self.assertEqual(al[1], data.Field(unsigned(2), 2))
self.assertEqual(al[2], Field(unsigned(2), 4)) self.assertEqual(al[2], data.Field(unsigned(2), 4))
self.assertEqual(al[-1], Field(unsigned(2), 4)) self.assertEqual(al[-1], data.Field(unsigned(2), 4))
self.assertEqual(al[-2], Field(unsigned(2), 2)) self.assertEqual(al[-2], data.Field(unsigned(2), 2))
self.assertEqual(al[-3], Field(unsigned(2), 0)) self.assertEqual(al[-3], data.Field(unsigned(2), 0))
self.assertEqual(al.size, 6) self.assertEqual(al.size, 6)
def test_shape_castable(self): def test_shape_castable(self):
al = ArrayLayout(2, 3) al = data.ArrayLayout(2, 3)
self.assertEqual(al.size, 6) self.assertEqual(al.size, 6)
def test_eq(self): def test_eq(self):
self.assertEqual(ArrayLayout(unsigned(2), 3), self.assertEqual(data.ArrayLayout(unsigned(2), 3),
ArrayLayout(unsigned(2), 3)) data.ArrayLayout(unsigned(2), 3))
self.assertNotEqual(ArrayLayout(unsigned(2), 3), self.assertNotEqual(data.ArrayLayout(unsigned(2), 3),
ArrayLayout(unsigned(2), 4)) data.ArrayLayout(unsigned(2), 4))
def test_repr(self): def test_repr(self):
al = ArrayLayout(unsigned(2), 3) al = data.ArrayLayout(unsigned(2), 3)
self.assertEqual(repr(al), "ArrayLayout(unsigned(2), 3)") self.assertEqual(repr(al), "ArrayLayout(unsigned(2), 3)")
def test_elem_shape_wrong(self): def test_elem_shape_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Array layout element shape must be a shape-castable object, not <.+>$"): r"^Array layout element shape must be a shape-castable object, not <.+>$"):
ArrayLayout(object(), 1) data.ArrayLayout(object(), 1)
def test_length_wrong(self): def test_length_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Array layout length must be a non-negative integer, not <.+>$"): r"^Array layout length must be a non-negative integer, not <.+>$"):
ArrayLayout(unsigned(1), object()) data.ArrayLayout(unsigned(1), object())
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Array layout length must be a non-negative integer, not -1$"): r"^Array layout length must be a non-negative integer, not -1$"):
ArrayLayout(unsigned(1), -1) data.ArrayLayout(unsigned(1), -1)
def test_key_wrong_bounds(self): def test_key_wrong_bounds(self):
al = ArrayLayout(unsigned(2), 3) al = data.ArrayLayout(unsigned(2), 3)
with self.assertRaisesRegex(KeyError, r"^4$"): with self.assertRaisesRegex(KeyError, r"^4$"):
al[4] al[4]
with self.assertRaisesRegex(KeyError, r"^-4$"): with self.assertRaisesRegex(KeyError, r"^-4$"):
al[-4] al[-4]
def test_key_wrong_type(self): def test_key_wrong_type(self):
al = ArrayLayout(unsigned(2), 3) al = data.ArrayLayout(unsigned(2), 3)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Cannot index array layout with 'a'$"): r"^Cannot index array layout with 'a'$"):
al["a"] al["a"]
@ -244,54 +243,54 @@ class ArrayLayoutTestCase(TestCase):
class FlexibleLayoutTestCase(TestCase): class FlexibleLayoutTestCase(TestCase):
def test_construct(self): def test_construct(self):
il = FlexibleLayout(8, { il = data.FlexibleLayout(8, {
"a": Field(unsigned(1), 1), "a": data.Field(unsigned(1), 1),
"b": Field(unsigned(3), 0), "b": data.Field(unsigned(3), 0),
0: Field(unsigned(2), 5) 0: data.Field(unsigned(2), 5)
}) })
self.assertEqual(il.size, 8) self.assertEqual(il.size, 8)
self.assertEqual(il.fields, { self.assertEqual(il.fields, {
"a": Field(unsigned(1), 1), "a": data.Field(unsigned(1), 1),
"b": Field(unsigned(3), 0), "b": data.Field(unsigned(3), 0),
0: Field(unsigned(2), 5) 0: data.Field(unsigned(2), 5)
}) })
self.assertEqual(list(iter(il)), [ self.assertEqual(list(iter(il)), [
("a", Field(unsigned(1), 1)), ("a", data.Field(unsigned(1), 1)),
("b", Field(unsigned(3), 0)), ("b", data.Field(unsigned(3), 0)),
(0, Field(unsigned(2), 5)) (0, data.Field(unsigned(2), 5))
]) ])
self.assertEqual(il["a"], Field(unsigned(1), 1)) self.assertEqual(il["a"], data.Field(unsigned(1), 1))
self.assertEqual(il["b"], Field(unsigned(3), 0)) self.assertEqual(il["b"], data.Field(unsigned(3), 0))
self.assertEqual(il[0], Field(unsigned(2), 5)) self.assertEqual(il[0], data.Field(unsigned(2), 5))
def test_is_not_mutated(self): def test_is_not_mutated(self):
il = FlexibleLayout(8, {"a": Field(unsigned(1), 0)}) il = data.FlexibleLayout(8, {"a": data.Field(unsigned(1), 0)})
del il.fields["a"] del il.fields["a"]
self.assertIn("a", il.fields) self.assertIn("a", il.fields)
def test_eq(self): def test_eq(self):
self.assertEqual(FlexibleLayout(3, {"a": Field(unsigned(1), 0)}), self.assertEqual(data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 0)}),
FlexibleLayout(3, {"a": Field(unsigned(1), 0)})) data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 0)}))
self.assertNotEqual(FlexibleLayout(3, {"a": Field(unsigned(1), 0)}), self.assertNotEqual(data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 0)}),
FlexibleLayout(4, {"a": Field(unsigned(1), 0)})) data.FlexibleLayout(4, {"a": data.Field(unsigned(1), 0)}))
self.assertNotEqual(FlexibleLayout(3, {"a": Field(unsigned(1), 0)}), self.assertNotEqual(data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 0)}),
FlexibleLayout(3, {"a": Field(unsigned(1), 1)})) data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 1)}))
def test_eq_duck(self): def test_eq_duck(self):
self.assertEqual(FlexibleLayout(3, {"a": Field(unsigned(1), 0), self.assertEqual(data.FlexibleLayout(3, {"a": data.Field(unsigned(1), 0),
"b": Field(unsigned(2), 1)}), "b": data.Field(unsigned(2), 1)}),
StructLayout({"a": unsigned(1), data.StructLayout({"a": unsigned(1),
"b": unsigned(2)})) "b": unsigned(2)}))
self.assertEqual(FlexibleLayout(2, {"a": Field(unsigned(1), 0), self.assertEqual(data.FlexibleLayout(2, {"a": data.Field(unsigned(1), 0),
"b": Field(unsigned(2), 0)}), "b": data.Field(unsigned(2), 0)}),
UnionLayout({"a": unsigned(1), data.UnionLayout({"a": unsigned(1),
"b": unsigned(2)})) "b": unsigned(2)}))
def test_repr(self): def test_repr(self):
il = FlexibleLayout(8, { il = data.FlexibleLayout(8, {
"a": Field(unsigned(1), 1), "a": data.Field(unsigned(1), 1),
"b": Field(unsigned(3), 0), "b": data.Field(unsigned(3), 0),
0: Field(unsigned(2), 5) 0: data.Field(unsigned(2), 5)
}) })
self.assertEqual(repr(il), "FlexibleLayout(8, {" self.assertEqual(repr(il), "FlexibleLayout(8, {"
"'a': Field(unsigned(1), 1), " "'a': Field(unsigned(1), 1), "
@ -301,44 +300,44 @@ class FlexibleLayoutTestCase(TestCase):
def test_fields_wrong(self): def test_fields_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Flexible layout fields must be provided as a mapping, not <.+>$"): r"^Flexible layout fields must be provided as a mapping, not <.+>$"):
FlexibleLayout(8, object()) data.FlexibleLayout(8, object())
def test_field_key_wrong(self): def test_field_key_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Flexible layout field name must be a non-negative integer or a string, " r"^Flexible layout field name must be a non-negative integer or a string, "
r"not 1\.0$"): r"not 1\.0$"):
FlexibleLayout(8, {1.0: unsigned(1)}) data.FlexibleLayout(8, {1.0: unsigned(1)})
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Flexible layout field name must be a non-negative integer or a string, " r"^Flexible layout field name must be a non-negative integer or a string, "
r"not -1$"): r"not -1$"):
FlexibleLayout(8, {-1: unsigned(1)}) data.FlexibleLayout(8, {-1: unsigned(1)})
def test_field_value_wrong(self): def test_field_value_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Flexible layout field value must be a Field instance, not 1\.0$"): r"^Flexible layout field value must be a Field instance, not 1\.0$"):
FlexibleLayout(8, {"a": 1.0}) data.FlexibleLayout(8, {"a": 1.0})
def test_size_wrong_negative(self): def test_size_wrong_negative(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Flexible layout size must be a non-negative integer, not -1$"): r"^Flexible layout size must be a non-negative integer, not -1$"):
FlexibleLayout(-1, {}) data.FlexibleLayout(-1, {})
def test_size_wrong_small(self): def test_size_wrong_small(self):
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Flexible layout field 'a' ends at bit 8, exceeding the size of 4 bit\(s\)$"): r"^Flexible layout field 'a' ends at bit 8, exceeding the size of 4 bit\(s\)$"):
FlexibleLayout(4, {"a": Field(unsigned(8), 0)}) data.FlexibleLayout(4, {"a": data.Field(unsigned(8), 0)})
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Flexible layout field 'a' ends at bit 5, exceeding the size of 4 bit\(s\)$"): r"^Flexible layout field 'a' ends at bit 5, exceeding the size of 4 bit\(s\)$"):
FlexibleLayout(4, {"a": Field(unsigned(2), 3)}) data.FlexibleLayout(4, {"a": data.Field(unsigned(2), 3)})
def test_key_wrong_missing(self): def test_key_wrong_missing(self):
il = FlexibleLayout(8, {"a": Field(unsigned(2), 3)}) il = data.FlexibleLayout(8, {"a": data.Field(unsigned(2), 3)})
with self.assertRaisesRegex(KeyError, with self.assertRaisesRegex(KeyError,
r"^0$"): r"^0$"):
il[0] il[0]
def test_key_wrong_type(self): def test_key_wrong_type(self):
il = FlexibleLayout(8, {"a": Field(unsigned(2), 3)}) il = data.FlexibleLayout(8, {"a": data.Field(unsigned(2), 3)})
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Cannot index flexible layout with <.+>$"): r"^Cannot index flexible layout with <.+>$"):
il[object()] il[object()]
@ -346,62 +345,62 @@ class FlexibleLayoutTestCase(TestCase):
class LayoutTestCase(FHDLTestCase): class LayoutTestCase(FHDLTestCase):
def test_cast(self): def test_cast(self):
sl = StructLayout({}) sl = data.StructLayout({})
self.assertIs(Layout.cast(sl), sl) self.assertIs(data.Layout.cast(sl), sl)
def test_cast_wrong_not_layout(self): def test_cast_wrong_not_layout(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Object unsigned\(1\) cannot be converted to a data layout$"): r"^Object unsigned\(1\) cannot be converted to a data layout$"):
Layout.cast(unsigned(1)) data.Layout.cast(unsigned(1))
def test_cast_wrong_type(self): def test_cast_wrong_type(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Object <.+> cannot be converted to an Amaranth shape$"): r"^Object <.+> cannot be converted to an Amaranth shape$"):
Layout.cast(object()) data.Layout.cast(object())
def test_cast_wrong_recur(self): def test_cast_wrong_recur(self):
sc = MockShapeCastable(None) sc = MockShapeCastable(None)
sc.shape = sc sc.shape = sc
with self.assertRaisesRegex(RecursionError, with self.assertRaisesRegex(RecursionError,
r"^Shape-castable object <.+> casts to itself$"): r"^Shape-castable object <.+> casts to itself$"):
Layout.cast(sc) data.Layout.cast(sc)
def test_eq_wrong_recur(self): def test_eq_wrong_recur(self):
sc = MockShapeCastable(None) sc = MockShapeCastable(None)
sc.shape = sc sc.shape = sc
self.assertNotEqual(StructLayout({}), sc) self.assertNotEqual(data.StructLayout({}), sc)
def test_call(self): def test_call(self):
sl = StructLayout({"f": unsigned(1)}) sl = data.StructLayout({"f": unsigned(1)})
s = Signal(1) s = Signal(1)
v = sl(s) v = sl(s)
self.assertIs(v.shape(), sl) self.assertIs(v.shape(), sl)
self.assertIs(v.as_value(), s) self.assertIs(v.as_value(), s)
def test_const(self): def test_const(self):
sl = StructLayout({ sl = data.StructLayout({
"a": unsigned(1), "a": unsigned(1),
"b": unsigned(2) "b": unsigned(2)
}) })
self.assertRepr(sl.const(None).as_value(), "(const 3'd0)") self.assertRepr(sl.const(None).as_value(), "(const 3'd0)")
self.assertRepr(sl.const({"a": 0b1, "b": 0b10}).as_value(), "(const 3'd5)") self.assertRepr(sl.const({"a": 0b1, "b": 0b10}).as_value(), "(const 3'd5)")
fl = FlexibleLayout(2, { fl = data.FlexibleLayout(2, {
"a": Field(unsigned(1), 0), "a": data.Field(unsigned(1), 0),
"b": Field(unsigned(2), 0) "b": data.Field(unsigned(2), 0)
}) })
self.assertRepr(fl.const({"a": 0b11}).as_value(), "(const 2'd1)") self.assertRepr(fl.const({"a": 0b11}).as_value(), "(const 2'd1)")
self.assertRepr(fl.const({"b": 0b10}).as_value(), "(const 2'd2)") self.assertRepr(fl.const({"b": 0b10}).as_value(), "(const 2'd2)")
self.assertRepr(fl.const({"a": 0b1, "b": 0b10}).as_value(), "(const 2'd2)") self.assertRepr(fl.const({"a": 0b1, "b": 0b10}).as_value(), "(const 2'd2)")
sls = StructLayout({ sls = data.StructLayout({
"a": signed(4), "a": signed(4),
"b": signed(4) "b": signed(4)
}) })
self.assertRepr(sls.const({"b": 0, "a": -1}).as_value(), "(const 8'd15)") self.assertRepr(sls.const({"b": 0, "a": -1}).as_value(), "(const 8'd15)")
def test_const_wrong(self): def test_const_wrong(self):
sl = StructLayout({"f": unsigned(1)}) sl = data.StructLayout({"f": unsigned(1)})
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Layout constant initializer must be a mapping or a sequence, not " r"^Layout constant initializer must be a mapping or a sequence, not "
r"<.+?object.+?>$"): r"<.+?object.+?>$"):
@ -418,7 +417,7 @@ class LayoutTestCase(FHDLTestCase):
def const(self, init): def const(self, init):
return int(init, 16) return int(init, 16)
sl = StructLayout({"f": CastableFromHex()}) sl = data.StructLayout({"f": CastableFromHex()})
self.assertRepr(sl.const({"f": "aa"}).as_value(), "(const 8'd170)") self.assertRepr(sl.const({"f": "aa"}).as_value(), "(const 8'd170)")
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
@ -427,11 +426,11 @@ class LayoutTestCase(FHDLTestCase):
sl.const({"f": "01"}) sl.const({"f": "01"})
def test_const_field_const(self): def test_const_field_const(self):
sl = StructLayout({"f": unsigned(1)}) sl = data.StructLayout({"f": unsigned(1)})
self.assertRepr(sl.const({"f": Const(1)}).as_value(), "(const 1'd1)") self.assertRepr(sl.const({"f": Const(1)}).as_value(), "(const 1'd1)")
def test_signal_init(self): def test_signal_init(self):
sl = StructLayout({ sl = data.StructLayout({
"a": unsigned(1), "a": unsigned(1),
"b": unsigned(2) "b": unsigned(2)
}) })
@ -442,73 +441,73 @@ class LayoutTestCase(FHDLTestCase):
class ViewTestCase(FHDLTestCase): class ViewTestCase(FHDLTestCase):
def test_construct(self): def test_construct(self):
s = Signal(3) s = Signal(3)
v = View(StructLayout({"a": unsigned(1), "b": unsigned(2)}), s) v = data.View(data.StructLayout({"a": unsigned(1), "b": unsigned(2)}), s)
self.assertIs(Value.cast(v), s) self.assertIs(Value.cast(v), s)
self.assertRepr(v["a"], "(slice (sig s) 0:1)") self.assertRepr(v["a"], "(slice (sig s) 0:1)")
self.assertRepr(v["b"], "(slice (sig s) 1:3)") self.assertRepr(v["b"], "(slice (sig s) 1:3)")
def test_construct_signal(self): def test_construct_signal(self):
v = Signal(StructLayout({"a": unsigned(1), "b": unsigned(2)})) v = Signal(data.StructLayout({"a": unsigned(1), "b": unsigned(2)}))
cv = Value.cast(v) cv = Value.cast(v)
self.assertIsInstance(cv, Signal) self.assertIsInstance(cv, Signal)
self.assertEqual(cv.shape(), unsigned(3)) self.assertEqual(cv.shape(), unsigned(3))
self.assertEqual(cv.name, "v") self.assertEqual(cv.name, "v")
def test_construct_signal_init(self): def test_construct_signal_init(self):
v1 = Signal(StructLayout({"a": unsigned(1), "b": unsigned(2)}), v1 = Signal(data.StructLayout({"a": unsigned(1), "b": unsigned(2)}),
init={"a": 0b1, "b": 0b10}) init={"a": 0b1, "b": 0b10})
self.assertEqual(Value.cast(v1).init, 0b101) self.assertEqual(Value.cast(v1).init, 0b101)
v2 = Signal(StructLayout({"a": unsigned(1), v2 = Signal(data.StructLayout({"a": unsigned(1),
"b": StructLayout({"x": unsigned(1), "y": unsigned(1)})}), "b": data.StructLayout({"x": unsigned(1), "y": unsigned(1)})}),
init={"a": 0b1, "b": {"x": 0b0, "y": 0b1}}) init={"a": 0b1, "b": {"x": 0b0, "y": 0b1}})
self.assertEqual(Value.cast(v2).init, 0b101) self.assertEqual(Value.cast(v2).init, 0b101)
v3 = Signal(ArrayLayout(unsigned(2), 2), v3 = Signal(data.ArrayLayout(unsigned(2), 2),
init=[0b01, 0b10]) init=[0b01, 0b10])
self.assertEqual(Value.cast(v3).init, 0b1001) self.assertEqual(Value.cast(v3).init, 0b1001)
def test_layout_wrong(self): def test_layout_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^View layout must be a layout, not <.+?>$"): r"^View layout must be a layout, not <.+?>$"):
View(object(), Signal(1)) data.View(object(), Signal(1))
def test_layout_conflict_with_attr(self): def test_layout_conflict_with_attr(self):
with self.assertWarnsRegex(SyntaxWarning, with self.assertWarnsRegex(SyntaxWarning,
r"^View layout includes a field 'as_value' that will be shadowed by the view " r"^View layout includes a field 'as_value' that will be shadowed by the view "
r"attribute 'amaranth\.lib\.data\.View\.as_value'$"): r"attribute 'amaranth\.lib\.data\.View\.as_value'$"):
View(StructLayout({"as_value": unsigned(1)}), Signal(1)) data.View(data.StructLayout({"as_value": unsigned(1)}), Signal(1))
def test_layout_conflict_with_attr_derived(self): def test_layout_conflict_with_attr_derived(self):
class DerivedView(View): class DerivedView(data.View):
def foo(self): def foo(self):
pass pass
with self.assertWarnsRegex(SyntaxWarning, with self.assertWarnsRegex(SyntaxWarning,
r"^View layout includes a field 'foo' that will be shadowed by the view " r"^View layout includes a field 'foo' that will be shadowed by the view "
r"attribute 'tests\.test_lib_data\.ViewTestCase\." r"attribute 'tests\.test_lib_data\.ViewTestCase\."
r"test_layout_conflict_with_attr_derived\.<locals>.DerivedView\.foo'$"): r"test_layout_conflict_with_attr_derived\.<locals>.DerivedView\.foo'$"):
DerivedView(StructLayout({"foo": unsigned(1)}), Signal(1)) DerivedView(data.StructLayout({"foo": unsigned(1)}), Signal(1))
def test_target_wrong_type(self): def test_target_wrong_type(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^View target must be a value-castable object, not <.+?>$"): r"^View target must be a value-castable object, not <.+?>$"):
View(StructLayout({}), object()) data.View(data.StructLayout({}), object())
def test_target_wrong_size(self): def test_target_wrong_size(self):
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^View target is 2 bit\(s\) wide, which is not compatible with the 1 bit\(s\) " r"^View target is 2 bit\(s\) wide, which is not compatible with the 1 bit\(s\) "
r"wide view layout$"): r"wide view layout$"):
View(StructLayout({"a": unsigned(1)}), Signal(2)) data.View(data.StructLayout({"a": unsigned(1)}), Signal(2))
def test_getitem(self): def test_getitem(self):
v = Signal(UnionLayout({ v = Signal(data.UnionLayout({
"a": unsigned(2), "a": unsigned(2),
"s": StructLayout({ "s": data.StructLayout({
"b": unsigned(1), "b": unsigned(1),
"c": unsigned(3) "c": unsigned(3)
}), }),
"p": 1, "p": 1,
"q": signed(1), "q": signed(1),
"r": ArrayLayout(unsigned(2), 2), "r": data.ArrayLayout(unsigned(2), 2),
"t": ArrayLayout(StructLayout({ "t": data.ArrayLayout(data.StructLayout({
"u": unsigned(1), "u": unsigned(1),
"v": unsigned(1) "v": unsigned(1)
}), 2), }), 2),
@ -541,7 +540,7 @@ class ViewTestCase(FHDLTestCase):
def const(self, init): def const(self, init):
return Const(init, 2) return Const(init, 2)
v = Signal(StructLayout({ v = Signal(data.StructLayout({
"f": Reverser() "f": Reverser()
})) }))
self.assertRepr(v.f, "(cat (slice (slice (sig v) 0:2) 1:2) " self.assertRepr(v.f, "(cat (slice (slice (sig v) 0:2) 1:2) "
@ -558,7 +557,7 @@ class ViewTestCase(FHDLTestCase):
def const(self, init): def const(self, init):
return Const(init, 2) return Const(init, 2)
v = Signal(StructLayout({ v = Signal(data.StructLayout({
"f": WrongCastable() "f": WrongCastable()
})) }))
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
@ -569,18 +568,18 @@ class ViewTestCase(FHDLTestCase):
def test_index_wrong_missing(self): def test_index_wrong_missing(self):
with self.assertRaisesRegex(KeyError, with self.assertRaisesRegex(KeyError,
r"^'a'$"): r"^'a'$"):
Signal(StructLayout({}))["a"] Signal(data.StructLayout({}))["a"]
def test_index_wrong_struct_dynamic(self): def test_index_wrong_struct_dynamic(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Only views with array layout, not StructLayout\(\{\}\), may be indexed " r"^Only views with array layout, not StructLayout\(\{\}\), may be indexed "
r"with a value$"): r"with a value$"):
Signal(StructLayout({}))[Signal(1)] Signal(data.StructLayout({}))[Signal(1)]
def test_getattr(self): def test_getattr(self):
v = Signal(UnionLayout({ v = Signal(data.UnionLayout({
"a": unsigned(2), "a": unsigned(2),
"s": StructLayout({ "s": data.StructLayout({
"b": unsigned(1), "b": unsigned(1),
"c": unsigned(3) "c": unsigned(3)
}), }),
@ -600,7 +599,7 @@ class ViewTestCase(FHDLTestCase):
self.assertEqual(v.q.shape(), signed(1)) self.assertEqual(v.q.shape(), signed(1))
def test_getattr_reserved(self): def test_getattr_reserved(self):
v = Signal(UnionLayout({ v = Signal(data.UnionLayout({
"_a": unsigned(2) "_a": unsigned(2)
})) }))
self.assertRepr(v["_a"], "(slice (sig v) 0:2)") self.assertRepr(v["_a"], "(slice (sig v) 0:2)")
@ -609,34 +608,34 @@ class ViewTestCase(FHDLTestCase):
with self.assertRaisesRegex(AttributeError, with self.assertRaisesRegex(AttributeError,
r"^View of \(sig \$signal\) does not have a field 'a'; " r"^View of \(sig \$signal\) does not have a field 'a'; "
r"did you mean one of: 'b', 'c'\?$"): r"did you mean one of: 'b', 'c'\?$"):
Signal(StructLayout({"b": unsigned(1), "c": signed(1)})).a Signal(data.StructLayout({"b": unsigned(1), "c": signed(1)})).a
def test_attr_wrong_reserved(self): def test_attr_wrong_reserved(self):
with self.assertRaisesRegex(AttributeError, with self.assertRaisesRegex(AttributeError,
r"^View of \(sig \$signal\) field '_c' has a reserved name " r"^View of \(sig \$signal\) field '_c' has a reserved name "
r"and may only be accessed by indexing$"): r"and may only be accessed by indexing$"):
Signal(StructLayout({"_c": signed(1)}))._c Signal(data.StructLayout({"_c": signed(1)}))._c
def test_signal_like(self): def test_signal_like(self):
s1 = Signal(StructLayout({"a": unsigned(1)})) s1 = Signal(data.StructLayout({"a": unsigned(1)}))
s2 = Signal.like(s1) s2 = Signal.like(s1)
self.assertEqual(s2.shape(), StructLayout({"a": unsigned(1)})) self.assertEqual(s2.shape(), data.StructLayout({"a": unsigned(1)}))
def test_bug_837_array_layout_getitem_str(self): def test_bug_837_array_layout_getitem_str(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Views with array layout may only be indexed with an integer or a value, " r"^Views with array layout may only be indexed with an integer or a value, "
r"not 'init'$"): r"not 'init'$"):
Signal(ArrayLayout(unsigned(1), 1), init=[0])["init"] Signal(data.ArrayLayout(unsigned(1), 1), init=[0])["init"]
def test_bug_837_array_layout_getattr(self): def test_bug_837_array_layout_getattr(self):
with self.assertRaisesRegex(AttributeError, with self.assertRaisesRegex(AttributeError,
r"^View of \(sig \$signal\) with an array layout does not have fields$"): r"^View of \(sig \$signal\) with an array layout does not have fields$"):
Signal(ArrayLayout(unsigned(1), 1), init=[0]).init Signal(data.ArrayLayout(unsigned(1), 1), init=[0]).init
def test_eq(self): def test_eq(self):
s1 = Signal(StructLayout({"a": unsigned(2)})) s1 = Signal(data.StructLayout({"a": unsigned(2)}))
s2 = Signal(StructLayout({"a": unsigned(2)})) s2 = Signal(data.StructLayout({"a": unsigned(2)}))
s3 = Signal(StructLayout({"a": unsigned(1), "b": unsigned(1)})) s3 = Signal(data.StructLayout({"a": unsigned(1), "b": unsigned(1)}))
self.assertRepr(s1 == s2, "(== (sig s1) (sig s2))") self.assertRepr(s1 == s2, "(== (sig s1) (sig s2))")
self.assertRepr(s1 != s2, "(!= (sig s1) (sig s2))") self.assertRepr(s1 != s2, "(!= (sig s1) (sig s2))")
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
@ -653,7 +652,7 @@ class ViewTestCase(FHDLTestCase):
s1 != Const(0, 2) s1 != Const(0, 2)
def test_operator(self): def test_operator(self):
s1 = Signal(StructLayout({"a": unsigned(2)})) s1 = Signal(data.StructLayout({"a": unsigned(2)}))
s2 = Signal(unsigned(2)) s2 = Signal(unsigned(2))
for op in [ for op in [
operator.__add__, operator.__add__,
@ -687,18 +686,18 @@ class ViewTestCase(FHDLTestCase):
op(s2, s1) op(s2, s1)
def test_repr(self): def test_repr(self):
s1 = Signal(StructLayout({"a": unsigned(2)})) s1 = Signal(data.StructLayout({"a": unsigned(2)}))
self.assertRepr(s1, "View(StructLayout({'a': unsigned(2)}), (sig s1))") self.assertRepr(s1, "View(StructLayout({'a': unsigned(2)}), (sig s1))")
class StructTestCase(FHDLTestCase): class StructTestCase(FHDLTestCase):
def test_construct(self): def test_construct(self):
class S(Struct): class S(data.Struct):
a: unsigned(1) a: unsigned(1)
b: signed(3) b: signed(3)
self.assertEqual(Shape.cast(S), unsigned(4)) self.assertEqual(Shape.cast(S), unsigned(4))
self.assertEqual(Layout.cast(S), StructLayout({ self.assertEqual(data.Layout.cast(S), data.StructLayout({
"a": unsigned(1), "a": unsigned(1),
"b": signed(3) "b": signed(3)
})) }))
@ -711,13 +710,13 @@ class StructTestCase(FHDLTestCase):
self.assertRepr(v.b, "(s (slice (sig v) 1:4))") self.assertRepr(v.b, "(s (slice (sig v) 1:4))")
def test_construct_nested(self): def test_construct_nested(self):
Q = StructLayout({"r": signed(2), "s": signed(2)}) Q = data.StructLayout({"r": signed(2), "s": signed(2)})
class R(Struct): class R(data.Struct):
p: 4 p: 4
q: Q q: Q
class S(Struct): class S(data.Struct):
a: unsigned(1) a: unsigned(1)
b: R b: R
@ -729,14 +728,14 @@ class StructTestCase(FHDLTestCase):
self.assertIs(v.b.shape(), R) self.assertIs(v.b.shape(), R)
self.assertIsInstance(v.b, R) self.assertIsInstance(v.b, R)
self.assertIs(v.b.q.shape(), Q) self.assertIs(v.b.q.shape(), Q)
self.assertIsInstance(v.b.q, View) self.assertIsInstance(v.b.q, data.View)
self.assertRepr(v.b.p, "(slice (slice (sig v) 1:9) 0:4)") self.assertRepr(v.b.p, "(slice (slice (sig v) 1:9) 0:4)")
self.assertRepr(v.b.q.as_value(), "(slice (slice (sig v) 1:9) 4:8)") self.assertRepr(v.b.q.as_value(), "(slice (slice (sig v) 1:9) 4:8)")
self.assertRepr(v.b.q.r, "(s (slice (slice (slice (sig v) 1:9) 4:8) 0:2))") self.assertRepr(v.b.q.r, "(s (slice (slice (slice (sig v) 1:9) 4:8) 0:2))")
self.assertRepr(v.b.q.s, "(s (slice (slice (slice (sig v) 1:9) 4:8) 2:4))") self.assertRepr(v.b.q.s, "(s (slice (slice (slice (sig v) 1:9) 4:8) 2:4))")
def test_construct_init(self): def test_construct_init(self):
class S(Struct): class S(data.Struct):
p: 4 p: 4
q: 2 = 1 q: 2 = 1
@ -751,7 +750,7 @@ class StructTestCase(FHDLTestCase):
self.assertEqual(v3.as_value().init, 0b000011) self.assertEqual(v3.as_value().init, 0b000011)
def test_shape_undefined_wrong(self): def test_shape_undefined_wrong(self):
class S(Struct): class S(data.Struct):
pass pass
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
@ -759,7 +758,7 @@ class StructTestCase(FHDLTestCase):
Shape.cast(S) Shape.cast(S)
def test_base_class_1(self): def test_base_class_1(self):
class Sb(Struct): class Sb(data.Struct):
def add(self): def add(self):
return self.a + self.b return self.a + self.b
@ -775,7 +774,7 @@ class StructTestCase(FHDLTestCase):
self.assertEqual(Signal(Sb2).add().shape(), unsigned(3)) self.assertEqual(Signal(Sb2).add().shape(), unsigned(3))
def test_base_class_2(self): def test_base_class_2(self):
class Sb(Struct): class Sb(data.Struct):
a: 2 a: 2
b: 2 b: 2
@ -791,7 +790,7 @@ class StructTestCase(FHDLTestCase):
self.assertEqual(Signal(Sb2).do().shape(), unsigned(3)) self.assertEqual(Signal(Sb2).do().shape(), unsigned(3))
def test_layout_redefined_wrong(self): def test_layout_redefined_wrong(self):
class Sb(Struct): class Sb(data.Struct):
a: 1 a: 1
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
@ -800,17 +799,17 @@ class StructTestCase(FHDLTestCase):
b: 1 b: 1
def test_typing_annotation_coexistence(self): def test_typing_annotation_coexistence(self):
class S(Struct): class S(data.Struct):
a: unsigned(1) a: unsigned(1)
b: int b: int
c: str = "x" c: str = "x"
self.assertEqual(Layout.cast(S), StructLayout({"a": unsigned(1)})) self.assertEqual(data.Layout.cast(S), data.StructLayout({"a": unsigned(1)}))
self.assertEqual(S.__annotations__, {"b": int, "c": str}) self.assertEqual(S.__annotations__, {"b": int, "c": str})
self.assertEqual(S.c, "x") self.assertEqual(S.c, "x")
def test_signal_like(self): def test_signal_like(self):
class S(Struct): class S(data.Struct):
a: 1 a: 1
s1 = Signal(S) s1 = Signal(S)
s2 = Signal.like(s1) s2 = Signal.like(s1)
@ -819,12 +818,12 @@ class StructTestCase(FHDLTestCase):
class UnionTestCase(FHDLTestCase): class UnionTestCase(FHDLTestCase):
def test_construct(self): def test_construct(self):
class U(Union): class U(data.Union):
a: unsigned(1) a: unsigned(1)
b: signed(3) b: signed(3)
self.assertEqual(Shape.cast(U), unsigned(3)) self.assertEqual(Shape.cast(U), unsigned(3))
self.assertEqual(Layout.cast(U), UnionLayout({ self.assertEqual(data.Layout.cast(U), data.UnionLayout({
"a": unsigned(1), "a": unsigned(1),
"b": signed(3) "b": signed(3)
})) }))
@ -839,12 +838,12 @@ class UnionTestCase(FHDLTestCase):
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Initial value for at most one field can be provided for a union class " r"^Initial value for at most one field can be provided for a union class "
r"\(specified: a, b\)$"): r"\(specified: a, b\)$"):
class U(Union): class U(data.Union):
a: unsigned(1) = 1 a: unsigned(1) = 1
b: unsigned(2) = 1 b: unsigned(2) = 1
def test_construct_init_two_wrong(self): def test_construct_init_two_wrong(self):
class U(Union): class U(data.Union):
a: unsigned(1) a: unsigned(1)
b: unsigned(2) b: unsigned(2)
@ -856,7 +855,7 @@ class UnionTestCase(FHDLTestCase):
r"class \(specified: a, b\)$") r"class \(specified: a, b\)$")
def test_construct_init_override(self): def test_construct_init_override(self):
class U(Union): class U(data.Union):
a: unsigned(1) = 1 a: unsigned(1) = 1
b: unsigned(2) b: unsigned(2)
@ -875,7 +874,7 @@ class RFCExamplesTestCase(TestCase):
return wrapper return wrapper
def test_rfc_example_1(self): def test_rfc_example_1(self):
class Float32(Struct): class Float32(data.Struct):
fraction: unsigned(23) fraction: unsigned(23)
exponent: unsigned(8) exponent: unsigned(8)
sign: unsigned(1) sign: unsigned(1)
@ -896,7 +895,7 @@ class RFCExamplesTestCase(TestCase):
def check_m1(): def check_m1():
self.assertEqual((yield flt_a.as_value()), 0xbf800000) self.assertEqual((yield flt_a.as_value()), 0xbf800000)
class FloatOrInt32(Union): class FloatOrInt32(data.Union):
float: Float32 float: Float32
int: signed(32) int: signed(32)
@ -916,7 +915,7 @@ class RFCExamplesTestCase(TestCase):
ADD = 0 ADD = 0
SUB = 1 SUB = 1
adder_op_layout = StructLayout({ adder_op_layout = data.StructLayout({
"op": Op, "op": Op,
"a": Float32, "a": Float32,
"b": Float32 "b": Float32
@ -941,17 +940,17 @@ class RFCExamplesTestCase(TestCase):
ONE_SIGNED = 0 ONE_SIGNED = 0
TWO_UNSIGNED = 1 TWO_UNSIGNED = 1
layout1 = StructLayout({ layout1 = data.StructLayout({
"kind": Kind, "kind": Kind,
"value": UnionLayout({ "value": data.UnionLayout({
"one_signed": signed(2), "one_signed": signed(2),
"two_unsigned": ArrayLayout(unsigned(1), 2) "two_unsigned": data.ArrayLayout(unsigned(1), 2)
}) })
}) })
self.assertEqual(layout1.size, 3) self.assertEqual(layout1.size, 3)
view1 = Signal(layout1) view1 = Signal(layout1)
self.assertIsInstance(view1, View) self.assertIsInstance(view1, data.View)
self.assertEqual(view1.shape(), layout1) self.assertEqual(view1.shape(), layout1)
self.assertEqual(view1.as_value().shape(), unsigned(3)) self.assertEqual(view1.as_value().shape(), unsigned(3))
@ -965,10 +964,10 @@ class RFCExamplesTestCase(TestCase):
def check_m1(): def check_m1():
self.assertEqual((yield view1.as_value()), 0b011) self.assertEqual((yield view1.as_value()), 0b011)
class SomeVariant(Struct): class SomeVariant(data.Struct):
class Value(Union): class Value(data.Union):
one_signed: signed(2) one_signed: signed(2)
two_unsigned: ArrayLayout(unsigned(1), 2) two_unsigned: data.ArrayLayout(unsigned(1), 2)
kind: Kind kind: Kind
value: Value value: Value
@ -990,12 +989,12 @@ class RFCExamplesTestCase(TestCase):
def check_m2(): def check_m2():
self.assertEqual((yield view2.as_value()), 0b010) self.assertEqual((yield view2.as_value()), 0b010)
layout2 = StructLayout({ layout2 = data.StructLayout({
"ready": unsigned(1), "ready": unsigned(1),
"payload": SomeVariant "payload": SomeVariant
}) })
self.assertEqual(layout2.size, 4) self.assertEqual(layout2.size, 4)
self.assertEqual(layout1, Layout.cast(SomeVariant)) self.assertEqual(layout1, data.Layout.cast(SomeVariant))
self.assertIs(SomeVariant, view2.shape()) self.assertIs(SomeVariant, view2.shape())

View file

@ -1,21 +1,20 @@
# amaranth: UnusedElaboratable=no # amaranth: UnusedElaboratable=no
from amaranth.hdl._ast import * from amaranth.hdl import *
from amaranth.hdl._mem import MemoryInstance from amaranth.hdl._mem import MemoryInstance
from amaranth.lib.memory import * from amaranth.lib import memory, data
from amaranth.lib.data import *
from amaranth.lib.wiring import In, Out, SignatureMembers from amaranth.lib.wiring import In, Out, SignatureMembers
from .utils import * from .utils import *
class MyStruct(Struct): class MyStruct(data.Struct):
a: unsigned(3) a: unsigned(3)
b: signed(2) b: signed(2)
class WritePortTestCase(FHDLTestCase): class WritePortTestCase(FHDLTestCase):
def test_signature(self): def test_signature(self):
sig = WritePort.Signature(addr_width=2, shape=signed(4)) sig = memory.WritePort.Signature(addr_width=2, shape=signed(4))
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, signed(4)) self.assertEqual(sig.shape, signed(4))
self.assertEqual(sig.granularity, None) self.assertEqual(sig.granularity, None)
@ -24,7 +23,7 @@ class WritePortTestCase(FHDLTestCase):
"data": In(signed(4)), "data": In(signed(4)),
"en": In(1), "en": In(1),
})) }))
sig = WritePort.Signature(addr_width=2, shape=8, granularity=2) sig = memory.WritePort.Signature(addr_width=2, shape=8, granularity=2)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, 8) self.assertEqual(sig.shape, 8)
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
@ -32,15 +31,15 @@ class WritePortTestCase(FHDLTestCase):
"data": In(8), "data": In(8),
"en": In(4), "en": In(4),
})) }))
sig = WritePort.Signature(addr_width=2, shape=ArrayLayout(9, 8), granularity=2) sig = memory.WritePort.Signature(addr_width=2, shape=data.ArrayLayout(9, 8), granularity=2)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, ArrayLayout(9, 8)) self.assertEqual(sig.shape, data.ArrayLayout(9, 8))
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
"addr": In(2), "addr": In(2),
"data": In(ArrayLayout(9, 8)), "data": In(data.ArrayLayout(9, 8)),
"en": In(4), "en": In(4),
})) }))
sig = WritePort.Signature(addr_width=2, shape=0, granularity=0) sig = memory.WritePort.Signature(addr_width=2, shape=0, granularity=0)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, 0) self.assertEqual(sig.shape, 0)
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
@ -48,66 +47,66 @@ class WritePortTestCase(FHDLTestCase):
"data": In(0), "data": In(0),
"en": In(0), "en": In(0),
})) }))
sig = WritePort.Signature(addr_width=2, shape=ArrayLayout(9, 0), granularity=0) sig = memory.WritePort.Signature(addr_width=2, shape=data.ArrayLayout(9, 0), granularity=0)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, ArrayLayout(9, 0)) self.assertEqual(sig.shape, data.ArrayLayout(9, 0))
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
"addr": In(2), "addr": In(2),
"data": In(ArrayLayout(9, 0)), "data": In(data.ArrayLayout(9, 0)),
"en": In(0), "en": In(0),
})) }))
def test_signature_wrong(self): def test_signature_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
"^`addr_width` must be a non-negative int, not -2$"): "^`addr_width` must be a non-negative int, not -2$"):
WritePort.Signature(addr_width=-2, shape=8) memory.WritePort.Signature(addr_width=-2, shape=8)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
"^Granularity must be a non-negative int or None, not -2$"): "^Granularity must be a non-negative int or None, not -2$"):
WritePort.Signature(addr_width=4, shape=8, granularity=-2) memory.WritePort.Signature(addr_width=4, shape=8, granularity=-2)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
"^Granularity cannot be specified with signed shape$"): "^Granularity cannot be specified with signed shape$"):
WritePort.Signature(addr_width=2, shape=signed(8), granularity=2) memory.WritePort.Signature(addr_width=2, shape=signed(8), granularity=2)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
"^Granularity can only be specified for plain unsigned `Shape` or `ArrayLayout`$"): "^Granularity can only be specified for plain unsigned `Shape` or `ArrayLayout`$"):
WritePort.Signature(addr_width=2, shape=MyStruct, granularity=2) memory.WritePort.Signature(addr_width=2, shape=MyStruct, granularity=2)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
"^Granularity must be positive$"): "^Granularity must be positive$"):
WritePort.Signature(addr_width=2, shape=8, granularity=0) memory.WritePort.Signature(addr_width=2, shape=8, granularity=0)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
"^Granularity must be positive$"): "^Granularity must be positive$"):
WritePort.Signature(addr_width=2, shape=ArrayLayout(8, 8), granularity=0) memory.WritePort.Signature(addr_width=2, shape=data.ArrayLayout(8, 8), granularity=0)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
"^Granularity must divide data width$"): "^Granularity must divide data width$"):
WritePort.Signature(addr_width=2, shape=8, granularity=3) memory.WritePort.Signature(addr_width=2, shape=8, granularity=3)
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
"^Granularity must divide data array length$"): "^Granularity must divide data array length$"):
WritePort.Signature(addr_width=2, shape=ArrayLayout(8, 8), granularity=3) memory.WritePort.Signature(addr_width=2, shape=data.ArrayLayout(8, 8), granularity=3)
def test_signature_eq(self): def test_signature_eq(self):
sig = WritePort.Signature(addr_width=2, shape=8) sig = memory.WritePort.Signature(addr_width=2, shape=8)
self.assertEqual(sig, WritePort.Signature(addr_width=2, shape=8)) self.assertEqual(sig, memory.WritePort.Signature(addr_width=2, shape=8))
self.assertNotEqual(sig, WritePort.Signature(addr_width=2, shape=7)) self.assertNotEqual(sig, memory.WritePort.Signature(addr_width=2, shape=7))
self.assertNotEqual(sig, WritePort.Signature(addr_width=1, shape=8)) self.assertNotEqual(sig, memory.WritePort.Signature(addr_width=1, shape=8))
self.assertNotEqual(sig, WritePort.Signature(addr_width=2, shape=8, granularity=8)) self.assertNotEqual(sig, memory.WritePort.Signature(addr_width=2, shape=8, granularity=8))
sig = WritePort.Signature(addr_width=2, shape=8, granularity=4) sig = memory.WritePort.Signature(addr_width=2, shape=8, granularity=4)
self.assertEqual(sig, WritePort.Signature(addr_width=2, shape=8, granularity=4)) self.assertEqual(sig, memory.WritePort.Signature(addr_width=2, shape=8, granularity=4))
self.assertNotEqual(sig, WritePort.Signature(addr_width=2, shape=8, granularity=8)) self.assertNotEqual(sig, memory.WritePort.Signature(addr_width=2, shape=8, granularity=8))
def test_constructor(self): def test_constructor(self):
signature = WritePort.Signature(shape=MyStruct, addr_width=4) signature = memory.WritePort.Signature(shape=MyStruct, addr_width=4)
port = WritePort(signature, memory=None, domain="sync") port = memory.WritePort(signature, memory=None, domain="sync")
self.assertEqual(port.signature, signature) self.assertEqual(port.signature, signature)
self.assertIsNone(port.memory) self.assertIsNone(port.memory)
self.assertEqual(port.domain, "sync") self.assertEqual(port.domain, "sync")
self.assertIsInstance(port.addr, Signal) self.assertIsInstance(port.addr, Signal)
self.assertEqual(port.addr.shape(), unsigned(4)) self.assertEqual(port.addr.shape(), unsigned(4))
self.assertIsInstance(port.data, View) self.assertIsInstance(port.data, data.View)
self.assertEqual(port.data.shape(), MyStruct) self.assertEqual(port.data.shape(), MyStruct)
self.assertIsInstance(port.en, Signal) self.assertIsInstance(port.en, Signal)
self.assertEqual(port.en.shape(), unsigned(1)) self.assertEqual(port.en.shape(), unsigned(1))
signature = WritePort.Signature(shape=8, addr_width=4, granularity=2) signature = memory.WritePort.Signature(shape=8, addr_width=4, granularity=2)
port = WritePort(signature, memory=None, domain="sync") port = memory.WritePort(signature, memory=None, domain="sync")
self.assertEqual(port.signature, signature) self.assertEqual(port.signature, signature)
self.assertIsNone(port.memory) self.assertIsNone(port.memory)
self.assertEqual(port.domain, "sync") self.assertEqual(port.domain, "sync")
@ -118,40 +117,40 @@ class WritePortTestCase(FHDLTestCase):
self.assertIsInstance(port.en, Signal) self.assertIsInstance(port.en, Signal)
self.assertEqual(port.en.shape(), unsigned(4)) self.assertEqual(port.en.shape(), unsigned(4))
m = Memory(depth=16, shape=8, init=[]) m = memory.Memory(depth=16, shape=8, init=[])
port = WritePort(signature, memory=m, domain="sync") port = memory.WritePort(signature, memory=m, domain="sync")
self.assertIs(port.memory, m) self.assertIs(port.memory, m)
self.assertEqual(m.w_ports, (port,)) self.assertEqual(m.w_ports, (port,))
def test_constructor_wrong(self): def test_constructor_wrong(self):
signature = ReadPort.Signature(shape=8, addr_width=4) signature = memory.ReadPort.Signature(shape=8, addr_width=4)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Expected `WritePort.Signature`, not ReadPort.Signature\(.*\)$"): r"^Expected `WritePort.Signature`, not ReadPort.Signature\(.*\)$"):
WritePort(signature, memory=None, domain="sync") memory.WritePort(signature, memory=None, domain="sync")
signature = WritePort.Signature(shape=8, addr_width=4, granularity=2) signature = memory.WritePort.Signature(shape=8, addr_width=4, granularity=2)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Domain has to be a string, not None$"): r"^Domain has to be a string, not None$"):
WritePort(signature, memory=None, domain=None) memory.WritePort(signature, memory=None, domain=None)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Expected `Memory` or `None`, not 'a'$"): r"^Expected `Memory` or `None`, not 'a'$"):
WritePort(signature, memory="a", domain="sync") memory.WritePort(signature, memory="a", domain="sync")
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Write port domain cannot be \"comb\"$"): r"^Write port domain cannot be \"comb\"$"):
WritePort(signature, memory=None, domain="comb") memory.WritePort(signature, memory=None, domain="comb")
signature = WritePort.Signature(shape=8, addr_width=4) signature = memory.WritePort.Signature(shape=8, addr_width=4)
m = Memory(depth=8, shape=8, init=[]) m = memory.Memory(depth=8, shape=8, init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Memory address width 3 doesn't match port address width 4$"): r"^Memory address width 3 doesn't match port address width 4$"):
WritePort(signature, memory=m, domain="sync") memory.WritePort(signature, memory=m, domain="sync")
m = Memory(depth=16, shape=signed(8), init=[]) m = memory.Memory(depth=16, shape=signed(8), init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Memory shape signed\(8\) doesn't match port shape 8$"): r"^Memory shape signed\(8\) doesn't match port shape 8$"):
WritePort(signature, memory=m, domain="sync") memory.WritePort(signature, memory=m, domain="sync")
class ReadPortTestCase(FHDLTestCase): class ReadPortTestCase(FHDLTestCase):
def test_signature(self): def test_signature(self):
sig = ReadPort.Signature(addr_width=2, shape=signed(4)) sig = memory.ReadPort.Signature(addr_width=2, shape=signed(4))
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, signed(4)) self.assertEqual(sig.shape, signed(4))
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
@ -159,7 +158,7 @@ class ReadPortTestCase(FHDLTestCase):
"data": Out(signed(4)), "data": Out(signed(4)),
"en": In(1, init=1), "en": In(1, init=1),
})) }))
sig = ReadPort.Signature(addr_width=2, shape=8) sig = memory.ReadPort.Signature(addr_width=2, shape=8)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, 8) self.assertEqual(sig.shape, 8)
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
@ -167,7 +166,7 @@ class ReadPortTestCase(FHDLTestCase):
"data": Out(8), "data": Out(8),
"en": In(1, init=1), "en": In(1, init=1),
})) }))
sig = ReadPort.Signature(addr_width=2, shape=MyStruct) sig = memory.ReadPort.Signature(addr_width=2, shape=MyStruct)
self.assertEqual(sig.addr_width, 2) self.assertEqual(sig.addr_width, 2)
self.assertEqual(sig.shape, MyStruct) self.assertEqual(sig.shape, MyStruct)
self.assertEqual(sig.members, SignatureMembers({ self.assertEqual(sig.members, SignatureMembers({
@ -179,31 +178,31 @@ class ReadPortTestCase(FHDLTestCase):
def test_signature_wrong(self): def test_signature_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
"^`addr_width` must be a non-negative int, not -2$"): "^`addr_width` must be a non-negative int, not -2$"):
ReadPort.Signature(addr_width=-2, shape=8) memory.ReadPort.Signature(addr_width=-2, shape=8)
def test_signature_eq(self): def test_signature_eq(self):
sig = ReadPort.Signature(addr_width=2, shape=8) sig = memory.ReadPort.Signature(addr_width=2, shape=8)
self.assertEqual(sig, ReadPort.Signature(addr_width=2, shape=8)) self.assertEqual(sig, memory.ReadPort.Signature(addr_width=2, shape=8))
self.assertNotEqual(sig, ReadPort.Signature(addr_width=2, shape=7)) self.assertNotEqual(sig, memory.ReadPort.Signature(addr_width=2, shape=7))
self.assertNotEqual(sig, ReadPort.Signature(addr_width=1, shape=8)) self.assertNotEqual(sig, memory.ReadPort.Signature(addr_width=1, shape=8))
self.assertNotEqual(sig, WritePort.Signature(addr_width=2, shape=8)) self.assertNotEqual(sig, memory.WritePort.Signature(addr_width=2, shape=8))
def test_constructor(self): def test_constructor(self):
signature = ReadPort.Signature(shape=MyStruct, addr_width=4) signature = memory.ReadPort.Signature(shape=MyStruct, addr_width=4)
port = ReadPort(signature, memory=None, domain="sync") port = memory.ReadPort(signature, memory=None, domain="sync")
self.assertEqual(port.signature, signature) self.assertEqual(port.signature, signature)
self.assertIsNone(port.memory) self.assertIsNone(port.memory)
self.assertEqual(port.domain, "sync") self.assertEqual(port.domain, "sync")
self.assertIsInstance(port.addr, Signal) self.assertIsInstance(port.addr, Signal)
self.assertEqual(port.addr.shape(), unsigned(4)) self.assertEqual(port.addr.shape(), unsigned(4))
self.assertIsInstance(port.data, View) self.assertIsInstance(port.data, data.View)
self.assertEqual(port.data.shape(), MyStruct) self.assertEqual(port.data.shape(), MyStruct)
self.assertIsInstance(port.en, Signal) self.assertIsInstance(port.en, Signal)
self.assertEqual(port.en.shape(), unsigned(1)) self.assertEqual(port.en.shape(), unsigned(1))
self.assertEqual(port.transparent_for, ()) self.assertEqual(port.transparent_for, ())
signature = ReadPort.Signature(shape=8, addr_width=4) signature = memory.ReadPort.Signature(shape=8, addr_width=4)
port = ReadPort(signature, memory=None, domain="comb") port = memory.ReadPort(signature, memory=None, domain="comb")
self.assertEqual(port.signature, signature) self.assertEqual(port.signature, signature)
self.assertIsNone(port.memory) self.assertIsNone(port.memory)
self.assertEqual(port.domain, "comb") self.assertEqual(port.domain, "comb")
@ -216,60 +215,60 @@ class ReadPortTestCase(FHDLTestCase):
self.assertEqual(port.en.value, 1) self.assertEqual(port.en.value, 1)
self.assertEqual(port.transparent_for, ()) self.assertEqual(port.transparent_for, ())
m = Memory(depth=16, shape=8, init=[]) m = memory.Memory(depth=16, shape=8, init=[])
port = ReadPort(signature, memory=m, domain="sync") port = memory.ReadPort(signature, memory=m, domain="sync")
self.assertIs(port.memory, m) self.assertIs(port.memory, m)
self.assertEqual(m.r_ports, (port,)) self.assertEqual(m.r_ports, (port,))
write_port = m.write_port() write_port = m.write_port()
port = ReadPort(signature, memory=m, domain="sync", transparent_for=[write_port]) port = memory.ReadPort(signature, memory=m, domain="sync", transparent_for=[write_port])
self.assertIs(port.memory, m) self.assertIs(port.memory, m)
self.assertEqual(port.transparent_for, (write_port,)) self.assertEqual(port.transparent_for, (write_port,))
def test_constructor_wrong(self): def test_constructor_wrong(self):
signature = WritePort.Signature(shape=8, addr_width=4) signature = memory.WritePort.Signature(shape=8, addr_width=4)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Expected `ReadPort.Signature`, not WritePort.Signature\(.*\)$"): r"^Expected `ReadPort.Signature`, not WritePort.Signature\(.*\)$"):
ReadPort(signature, memory=None, domain="sync") memory.ReadPort(signature, memory=None, domain="sync")
signature = ReadPort.Signature(shape=8, addr_width=4) signature = memory.ReadPort.Signature(shape=8, addr_width=4)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Domain has to be a string, not None$"): r"^Domain has to be a string, not None$"):
ReadPort(signature, memory=None, domain=None) memory.ReadPort(signature, memory=None, domain=None)
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Expected `Memory` or `None`, not 'a'$"): r"^Expected `Memory` or `None`, not 'a'$"):
ReadPort(signature, memory="a", domain="sync") memory.ReadPort(signature, memory="a", domain="sync")
signature = ReadPort.Signature(shape=8, addr_width=4) signature = memory.ReadPort.Signature(shape=8, addr_width=4)
m = Memory(depth=8, shape=8, init=[]) m = memory.Memory(depth=8, shape=8, init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Memory address width 3 doesn't match port address width 4$"): r"^Memory address width 3 doesn't match port address width 4$"):
ReadPort(signature, memory=m, domain="sync") memory.ReadPort(signature, memory=m, domain="sync")
m = Memory(depth=16, shape=signed(8), init=[]) m = memory.Memory(depth=16, shape=signed(8), init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Memory shape signed\(8\) doesn't match port shape 8$"): r"^Memory shape signed\(8\) doesn't match port shape 8$"):
ReadPort(signature, memory=m, domain="sync") memory.ReadPort(signature, memory=m, domain="sync")
m = Memory(depth=16, shape=8, init=[]) m = memory.Memory(depth=16, shape=8, init=[])
port = m.read_port() port = m.read_port()
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^`transparent_for` must contain only `WritePort` instances$"): r"^`transparent_for` must contain only `WritePort` instances$"):
ReadPort(signature, memory=m, domain="sync", transparent_for=[port]) memory.ReadPort(signature, memory=m, domain="sync", transparent_for=[port])
write_port = m.write_port() write_port = m.write_port()
m2 = Memory(depth=16, shape=8, init=[]) m2 = memory.Memory(depth=16, shape=8, init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Transparent write ports must belong to the same memory$"): r"^Transparent write ports must belong to the same memory$"):
ReadPort(signature, memory=m2, domain="sync", transparent_for=[write_port]) memory.ReadPort(signature, memory=m2, domain="sync", transparent_for=[write_port])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Transparent write ports must belong to the same domain$"): r"^Transparent write ports must belong to the same domain$"):
ReadPort(signature, memory=m, domain="other", transparent_for=[write_port]) memory.ReadPort(signature, memory=m, domain="other", transparent_for=[write_port])
class MemoryTestCase(FHDLTestCase): class MemoryTestCase(FHDLTestCase):
def test_constructor(self): def test_constructor(self):
m = Memory(shape=8, depth=4, init=[1, 2, 3]) m = memory.Memory(shape=8, depth=4, init=[1, 2, 3])
self.assertEqual(m.shape, 8) self.assertEqual(m.shape, 8)
self.assertEqual(m.depth, 4) self.assertEqual(m.depth, 4)
self.assertEqual(m.init.shape, 8) self.assertEqual(m.init.shape, 8)
self.assertEqual(m.init.depth, 4) self.assertEqual(m.init.depth, 4)
self.assertEqual(m.attrs, {}) self.assertEqual(m.attrs, {})
self.assertIsInstance(m.init, Memory.Init) self.assertIsInstance(m.init, memory.Memory.Init)
self.assertEqual(list(m.init), [1, 2, 3, 0]) self.assertEqual(list(m.init), [1, 2, 3, 0])
self.assertEqual(m.init._raw, [1, 2, 3, 0]) self.assertEqual(m.init._raw, [1, 2, 3, 0])
self.assertRepr(m.init, "Memory.Init([1, 2, 3, 0])") self.assertRepr(m.init, "Memory.Init([1, 2, 3, 0])")
@ -281,31 +280,31 @@ class MemoryTestCase(FHDLTestCase):
{"a": 0, "b": 1}, {"a": 0, "b": 1},
{"a": 2, "b": 3}, {"a": 2, "b": 3},
] ]
m = Memory(shape=MyStruct, depth=4, init=init, attrs={"ram_style": "block"}) m = memory.Memory(shape=MyStruct, depth=4, init=init, attrs={"ram_style": "block"})
self.assertEqual(m.shape, MyStruct) self.assertEqual(m.shape, MyStruct)
self.assertEqual(m.depth, 4) self.assertEqual(m.depth, 4)
self.assertEqual(m.attrs, {"ram_style": "block"}) self.assertEqual(m.attrs, {"ram_style": "block"})
self.assertIsInstance(m.init, Memory.Init) self.assertIsInstance(m.init, memory.Memory.Init)
self.assertEqual(list(m.init), [{"a": 0, "b": 1}, {"a": 2, "b": 3}, None, None]) self.assertEqual(list(m.init), [{"a": 0, "b": 1}, {"a": 2, "b": 3}, None, None])
self.assertEqual(m.init._raw, [8, 0x1a, 0, 0]) self.assertEqual(m.init._raw, [8, 0x1a, 0, 0])
def test_constructor_wrong(self): def test_constructor_wrong(self):
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Memory depth must be a non-negative integer, not 'a'$"): r"^Memory depth must be a non-negative integer, not 'a'$"):
Memory(shape=8, depth="a", init=[]) memory.Memory(shape=8, depth="a", init=[])
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Memory depth must be a non-negative integer, not -1$"): r"^Memory depth must be a non-negative integer, not -1$"):
Memory(shape=8, depth=-1, init=[]) memory.Memory(shape=8, depth=-1, init=[])
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^Object 'a' cannot be converted to an Amaranth shape$"): r"^Object 'a' cannot be converted to an Amaranth shape$"):
Memory(shape="a", depth=3, init=[]) memory.Memory(shape="a", depth=3, init=[])
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
(r"^Memory initialization value at address 1: " (r"^Memory initialization value at address 1: "
r"'str' object cannot be interpreted as an integer$")): r"'str' object cannot be interpreted as an integer$")):
Memory(shape=8, depth=4, init=[1, "0"]) memory.Memory(shape=8, depth=4, init=[1, "0"])
def test_init_set(self): def test_init_set(self):
m = Memory(shape=8, depth=4, init=[]) m = memory.Memory(shape=8, depth=4, init=[])
m.init[1] = 2 m.init[1] = 2
self.assertEqual(list(m.init), [0, 2, 0, 0]) self.assertEqual(list(m.init), [0, 2, 0, 0])
self.assertEqual(m.init._raw, [0, 2, 0, 0]) self.assertEqual(m.init._raw, [0, 2, 0, 0])
@ -315,23 +314,23 @@ class MemoryTestCase(FHDLTestCase):
self.assertEqual(list(m.init), [6, 7, 0, 0]) self.assertEqual(list(m.init), [6, 7, 0, 0])
def test_init_set_shapecastable(self): def test_init_set_shapecastable(self):
m = Memory(shape=MyStruct, depth=4, init=[]) m = memory.Memory(shape=MyStruct, depth=4, init=[])
m.init[1] = {"a": 1, "b": 2} m.init[1] = {"a": 1, "b": 2}
self.assertEqual(list(m.init), [None, {"a": 1, "b": 2}, None, None]) self.assertEqual(list(m.init), [None, {"a": 1, "b": 2}, None, None])
self.assertEqual(m.init._raw, [0, 0x11, 0, 0]) self.assertEqual(m.init._raw, [0, 0x11, 0, 0])
def test_init_set_wrong(self): def test_init_set_wrong(self):
m = Memory(shape=8, depth=4, init=[]) m = memory.Memory(shape=8, depth=4, init=[])
with self.assertRaisesRegex(TypeError, with self.assertRaisesRegex(TypeError,
r"^'str' object cannot be interpreted as an integer$"): r"^'str' object cannot be interpreted as an integer$"):
m.init[0] = "a" m.init[0] = "a"
m = Memory(shape=MyStruct, depth=4, init=[]) m = memory.Memory(shape=MyStruct, depth=4, init=[])
# underlying TypeError message differs between PyPy and CPython # underlying TypeError message differs between PyPy and CPython
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
m.init[0] = 1 m.init[0] = 1
def test_init_set_slice_wrong(self): def test_init_set_slice_wrong(self):
m = Memory(shape=8, depth=4, init=[]) m = memory.Memory(shape=8, depth=4, init=[])
with self.assertRaisesRegex(ValueError, with self.assertRaisesRegex(ValueError,
r"^Changing length of Memory.init is not allowed$"): r"^Changing length of Memory.init is not allowed$"):
m.init[1:] = [1, 2] m.init[1:] = [1, 2]
@ -350,7 +349,7 @@ class MemoryTestCase(FHDLTestCase):
(4, 2), (4, 2),
(5, 3), (5, 3),
]: ]:
m = Memory(shape=8, depth=depth, init=[]) m = memory.Memory(shape=8, depth=depth, init=[])
rp = m.read_port() rp = m.read_port()
self.assertEqual(rp.signature.addr_width, addr_width) self.assertEqual(rp.signature.addr_width, addr_width)
self.assertEqual(rp.signature.shape, 8) self.assertEqual(rp.signature.shape, 8)
@ -361,7 +360,7 @@ class MemoryTestCase(FHDLTestCase):
self.assertEqual(m.w_ports, (wp,)) self.assertEqual(m.w_ports, (wp,))
def test_elaborate(self): def test_elaborate(self):
m = Memory(shape=MyStruct, depth=4, init=[{"a": 1, "b": 2}]) m = memory.Memory(shape=MyStruct, depth=4, init=[{"a": 1, "b": 2}])
wp = m.write_port() wp = m.write_port()
rp0 = m.read_port(domain="sync", transparent_for=[wp]) rp0 = m.read_port(domain="sync", transparent_for=[wp])
rp1 = m.read_port(domain="comb") rp1 = m.read_port(domain="comb")