tests: fix remove unnecessary workaround for some unittest assertions.
This commit is contained in:
parent
c75fa45fd8
commit
8117ef6692
|
@ -46,19 +46,19 @@ class PinsTestCase(FHDLTestCase):
|
||||||
self.assertEqual(p.map_names(mapping, p), ["A1"])
|
self.assertEqual(p.map_names(mapping, p), ["A1"])
|
||||||
|
|
||||||
def test_wrong_names(self):
|
def test_wrong_names(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Names must be a whitespace-separated string, not ['A0', 'A1', 'A2']"):
|
r"^Names must be a whitespace-separated string, not \['A0', 'A1', 'A2'\]$"):
|
||||||
p = Pins(["A0", "A1", "A2"])
|
p = Pins(["A0", "A1", "A2"])
|
||||||
|
|
||||||
def test_wrong_dir(self):
|
def test_wrong_dir(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not 'wrong'"):
|
r"^Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not 'wrong'$"):
|
||||||
p = Pins("A0 A1", dir="wrong")
|
p = Pins("A0 A1", dir="wrong")
|
||||||
|
|
||||||
def test_wrong_conn(self):
|
def test_wrong_conn(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Connector must be None or a pair of string (connector name) and "
|
(r"^Connector must be None or a pair of string \(connector name\) and "
|
||||||
"integer/string (connector number), not ('foo', None)"):
|
r"integer\/string \(connector number\), not \('foo', None\)$")):
|
||||||
p = Pins("A0 A1", conn=("foo", None))
|
p = Pins("A0 A1", conn=("foo", None))
|
||||||
|
|
||||||
def test_wrong_map_names(self):
|
def test_wrong_map_names(self):
|
||||||
|
@ -66,14 +66,14 @@ class PinsTestCase(FHDLTestCase):
|
||||||
mapping = {
|
mapping = {
|
||||||
"pmod_0:0": "A0",
|
"pmod_0:0": "A0",
|
||||||
}
|
}
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Resource (pins io pmod_0:0 pmod_0:1 pmod_0:2) refers to nonexistent "
|
(r"^Resource \(pins io pmod_0:0 pmod_0:1 pmod_0:2\) refers to nonexistent "
|
||||||
"connector pin pmod_0:1"):
|
r"connector pin pmod_0:1$")):
|
||||||
p.map_names(mapping, p)
|
p.map_names(mapping, p)
|
||||||
|
|
||||||
def test_wrong_assert_width(self):
|
def test_wrong_assert_width(self):
|
||||||
with self.assertRaises(AssertionError,
|
with self.assertRaisesRegex(AssertionError,
|
||||||
msg="3 names are specified (0 1 2), but 4 names are expected"):
|
r"^3 names are specified \(0 1 2\), but 4 names are expected$"):
|
||||||
Pins("0 1 2", assert_width=4)
|
Pins("0 1 2", assert_width=4)
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,14 +108,14 @@ class DiffPairsTestCase(FHDLTestCase):
|
||||||
self.assertEqual(dp.n.dir, "o")
|
self.assertEqual(dp.n.dir, "o")
|
||||||
|
|
||||||
def test_wrong_width(self):
|
def test_wrong_width(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Positive and negative pins must have the same width, but (pins io A0) "
|
(r"^Positive and negative pins must have the same width, but \(pins io A0\) "
|
||||||
"and (pins io B0 B1) do not"):
|
r"and \(pins io B0 B1\) do not$")):
|
||||||
dp = DiffPairs("A0", "B0 B1")
|
dp = DiffPairs("A0", "B0 B1")
|
||||||
|
|
||||||
def test_wrong_assert_width(self):
|
def test_wrong_assert_width(self):
|
||||||
with self.assertRaises(AssertionError,
|
with self.assertRaisesRegex(AssertionError,
|
||||||
msg="3 names are specified (0 1 2), but 4 names are expected"):
|
r"^3 names are specified \(0 1 2\), but 4 names are expected$"):
|
||||||
DiffPairs("0 1 2", "3 4 5", assert_width=4)
|
DiffPairs("0 1 2", "3 4 5", assert_width=4)
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,8 +137,8 @@ class AttrsTestCase(FHDLTestCase):
|
||||||
self.assertEqual(repr(a), "(attrs FOO={!r})".format(fn))
|
self.assertEqual(repr(a), "(attrs FOO={!r})".format(fn))
|
||||||
|
|
||||||
def test_wrong_value(self):
|
def test_wrong_value(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Value of attribute FOO must be None, int, str, or callable, not 1.0"):
|
r"^Value of attribute FOO must be None, int, str, or callable, not 1\.0$"):
|
||||||
a = Attrs(FOO=1.0)
|
a = Attrs(FOO=1.0)
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,42 +187,42 @@ class SubsignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s.clock.frequency, 1e6)
|
self.assertEqual(s.clock.frequency, 1e6)
|
||||||
|
|
||||||
def test_wrong_empty_io(self):
|
def test_wrong_empty_io(self):
|
||||||
with self.assertRaises(ValueError, msg="Missing I/O constraints"):
|
with self.assertRaisesRegex(ValueError, r"^Missing I\/O constraints$"):
|
||||||
s = Subsignal("a")
|
s = Subsignal("a")
|
||||||
|
|
||||||
def test_wrong_io(self):
|
def test_wrong_io(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Constraint must be one of Pins, DiffPairs, Subsignal, Attrs, or Clock, "
|
(r"^Constraint must be one of Pins, DiffPairs, Subsignal, Attrs, or Clock, "
|
||||||
"not 'wrong'"):
|
r"not 'wrong'$")):
|
||||||
s = Subsignal("a", "wrong")
|
s = Subsignal("a", "wrong")
|
||||||
|
|
||||||
def test_wrong_pins(self):
|
def test_wrong_pins(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||||
"constraints, but (pins io A1) appears after (pins io A0)"):
|
r"constraints, but \(pins io A1\) appears after \(pins io A0\)$")):
|
||||||
s = Subsignal("a", Pins("A0"), Pins("A1"))
|
s = Subsignal("a", Pins("A0"), Pins("A1"))
|
||||||
|
|
||||||
def test_wrong_diffpairs(self):
|
def test_wrong_diffpairs(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||||
"constraints, but (pins io A1) appears after (diffpairs io (p A0) (n B0))"):
|
r"constraints, but \(pins io A1\) appears after \(diffpairs io \(p A0\) \(n B0\)\)$")):
|
||||||
s = Subsignal("a", DiffPairs("A0", "B0"), Pins("A1"))
|
s = Subsignal("a", DiffPairs("A0", "B0"), Pins("A1"))
|
||||||
|
|
||||||
def test_wrong_subsignals(self):
|
def test_wrong_subsignals(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Pins and DiffPairs are incompatible with other location or subsignal "
|
(r"^Pins and DiffPairs are incompatible with other location or subsignal "
|
||||||
"constraints, but (pins io B0) appears after (subsignal b (pins io A0))"):
|
r"constraints, but \(pins io B0\) appears after \(subsignal b \(pins io A0\)\)$")):
|
||||||
s = Subsignal("a", Subsignal("b", Pins("A0")), Pins("B0"))
|
s = Subsignal("a", Subsignal("b", Pins("A0")), Pins("B0"))
|
||||||
|
|
||||||
def test_wrong_clock(self):
|
def test_wrong_clock(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Clock constraint can only be applied to Pins or DiffPairs, not "
|
(r"^Clock constraint can only be applied to Pins or DiffPairs, not "
|
||||||
"(subsignal b (pins io A0))"):
|
r"\(subsignal b \(pins io A0\)\)$")):
|
||||||
s = Subsignal("a", Subsignal("b", Pins("A0")), Clock(1e6))
|
s = Subsignal("a", Subsignal("b", Pins("A0")), Clock(1e6))
|
||||||
|
|
||||||
def test_wrong_clock_many(self):
|
def test_wrong_clock_many(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Clock constraint can be applied only once"):
|
r"^Clock constraint can be applied only once$"):
|
||||||
s = Subsignal("a", Pins("A0"), Clock(1e6), Clock(1e7))
|
s = Subsignal("a", Pins("A0"), Clock(1e6), Clock(1e7))
|
||||||
|
|
||||||
|
|
||||||
|
@ -309,20 +309,20 @@ class ConnectorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(c.number, "A")
|
self.assertEqual(c.number, "A")
|
||||||
|
|
||||||
def test_conn_wrong_name(self):
|
def test_conn_wrong_name(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Connector must be None or a pair of string (connector name) and "
|
(r"^Connector must be None or a pair of string \(connector name\) and "
|
||||||
"integer/string (connector number), not ('foo', None)"):
|
r"integer\/string \(connector number\), not \('foo', None\)$")):
|
||||||
Connector("ext", "A", "0 1 2", conn=("foo", None))
|
Connector("ext", "A", "0 1 2", conn=("foo", None))
|
||||||
|
|
||||||
def test_wrong_io(self):
|
def test_wrong_io(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Connector I/Os must be a dictionary or a string, not []"):
|
r"^Connector I\/Os must be a dictionary or a string, not \[\]$"):
|
||||||
Connector("pmod", 0, [])
|
Connector("pmod", 0, [])
|
||||||
|
|
||||||
def test_wrong_dict_key_value(self):
|
def test_wrong_dict_key_value(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Connector pin name must be a string, not 0"):
|
r"^Connector pin name must be a string, not 0$"):
|
||||||
Connector("pmod", 0, {0: "A"})
|
Connector("pmod", 0, {0: "A"})
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Platform pin name must be a string, not 0"):
|
r"^Platform pin name must be a string, not 0$"):
|
||||||
Connector("pmod", 0, {"A": 0})
|
Connector("pmod", 0, {"A": 0})
|
||||||
|
|
|
@ -36,17 +36,17 @@ class PlatformTestCase(FHDLTestCase):
|
||||||
self.assertEqual(self.platform.extra_files["x.txt"], f.read())
|
self.assertEqual(self.platform.extra_files["x.txt"], f.read())
|
||||||
|
|
||||||
def test_add_file_wrong_filename(self):
|
def test_add_file_wrong_filename(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="File name must be a string, not 1"):
|
r"^File name must be a string, not 1$"):
|
||||||
self.platform.add_file(1, "")
|
self.platform.add_file(1, "")
|
||||||
|
|
||||||
def test_add_file_wrong_contents(self):
|
def test_add_file_wrong_contents(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="File contents must be str, bytes, or a file-like object, not 1"):
|
r"^File contents must be str, bytes, or a file-like object, not 1$"):
|
||||||
self.platform.add_file("foo", 1)
|
self.platform.add_file("foo", 1)
|
||||||
|
|
||||||
def test_add_file_wrong_duplicate(self):
|
def test_add_file_wrong_duplicate(self):
|
||||||
self.platform.add_file("foo", "")
|
self.platform.add_file("foo", "")
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="File 'foo' already exists"):
|
r"^File 'foo' already exists$"):
|
||||||
self.platform.add_file("foo", "bar")
|
self.platform.add_file("foo", "bar")
|
||||||
|
|
|
@ -208,43 +208,43 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_wrong_resources(self):
|
def test_wrong_resources(self):
|
||||||
with self.assertRaises(TypeError, msg="Object 'wrong' is not a Resource"):
|
with self.assertRaisesRegex(TypeError, r"^Object 'wrong' is not a Resource$"):
|
||||||
self.cm.add_resources(['wrong'])
|
self.cm.add_resources(['wrong'])
|
||||||
|
|
||||||
def test_wrong_resources_duplicate(self):
|
def test_wrong_resources_duplicate(self):
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Trying to add (resource user_led 0 (pins o A1)), but "
|
(r"^Trying to add \(resource user_led 0 \(pins o A1\)\), but "
|
||||||
"(resource user_led 0 (pins o A0)) has the same name and number"):
|
r"\(resource user_led 0 \(pins o A0\)\) has the same name and number$")):
|
||||||
self.cm.add_resources([Resource("user_led", 0, Pins("A1", dir="o"))])
|
self.cm.add_resources([Resource("user_led", 0, Pins("A1", dir="o"))])
|
||||||
|
|
||||||
def test_wrong_connectors(self):
|
def test_wrong_connectors(self):
|
||||||
with self.assertRaises(TypeError, msg="Object 'wrong' is not a Connector"):
|
with self.assertRaisesRegex(TypeError, r"^Object 'wrong' is not a Connector$"):
|
||||||
self.cm.add_connectors(['wrong'])
|
self.cm.add_connectors(['wrong'])
|
||||||
|
|
||||||
def test_wrong_connectors_duplicate(self):
|
def test_wrong_connectors_duplicate(self):
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Trying to add (connector pmod 0 1=>1 2=>2), but "
|
(r"^Trying to add \(connector pmod 0 1=>1 2=>2\), but "
|
||||||
"(connector pmod 0 1=>B0 2=>B1 3=>B2 4=>B3) has the same name and number"):
|
r"\(connector pmod 0 1=>B0 2=>B1 3=>B2 4=>B3\) has the same name and number$")):
|
||||||
self.cm.add_connectors([Connector("pmod", 0, "1 2")])
|
self.cm.add_connectors([Connector("pmod", 0, "1 2")])
|
||||||
|
|
||||||
def test_wrong_lookup(self):
|
def test_wrong_lookup(self):
|
||||||
with self.assertRaises(ResourceError,
|
with self.assertRaisesRegex(ResourceError,
|
||||||
msg="Resource user_led#1 does not exist"):
|
r"^Resource user_led#1 does not exist$"):
|
||||||
r = self.cm.lookup("user_led", 1)
|
r = self.cm.lookup("user_led", 1)
|
||||||
|
|
||||||
def test_wrong_clock_signal(self):
|
def test_wrong_clock_signal(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Object None is not a Signal"):
|
r"^Object None is not a Signal$"):
|
||||||
self.cm.add_clock_constraint(None, 10e6)
|
self.cm.add_clock_constraint(None, 10e6)
|
||||||
|
|
||||||
def test_wrong_clock_frequency(self):
|
def test_wrong_clock_frequency(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Frequency must be a number, not None"):
|
r"^Frequency must be a number, not None$"):
|
||||||
self.cm.add_clock_constraint(Signal(), None)
|
self.cm.add_clock_constraint(Signal(), None)
|
||||||
|
|
||||||
def test_wrong_request_duplicate(self):
|
def test_wrong_request_duplicate(self):
|
||||||
with self.assertRaises(ResourceError,
|
with self.assertRaisesRegex(ResourceError,
|
||||||
msg="Resource user_led#0 has already been requested"):
|
r"^Resource user_led#0 has already been requested$"):
|
||||||
self.cm.request("user_led", 0)
|
self.cm.request("user_led", 0)
|
||||||
self.cm.request("user_led", 0)
|
self.cm.request("user_led", 0)
|
||||||
|
|
||||||
|
@ -253,46 +253,46 @@ class ResourceManagerTestCase(FHDLTestCase):
|
||||||
Resource("clk20", 0, Pins("H1", dir="i")),
|
Resource("clk20", 0, Pins("H1", dir="i")),
|
||||||
])
|
])
|
||||||
self.cm.request("clk100", 0)
|
self.cm.request("clk100", 0)
|
||||||
with self.assertRaises(ResourceError,
|
with self.assertRaisesRegex(ResourceError,
|
||||||
msg="Resource component clk20_0 uses physical pin H1, but it is already "
|
(r"^Resource component clk20_0 uses physical pin H1, but it is already "
|
||||||
"used by resource component clk100_0 that was requested earlier"):
|
r"used by resource component clk100_0 that was requested earlier$")):
|
||||||
self.cm.request("clk20", 0)
|
self.cm.request("clk20", 0)
|
||||||
|
|
||||||
def test_wrong_request_with_dir(self):
|
def test_wrong_request_with_dir(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Direction must be one of \"i\", \"o\", \"oe\", \"io\", or \"-\", "
|
(r"^Direction must be one of \"i\", \"o\", \"oe\", \"io\", or \"-\", "
|
||||||
"not 'wrong'"):
|
r"not 'wrong'$")):
|
||||||
user_led = self.cm.request("user_led", 0, dir="wrong")
|
user_led = self.cm.request("user_led", 0, dir="wrong")
|
||||||
|
|
||||||
def test_wrong_request_with_dir_io(self):
|
def test_wrong_request_with_dir_io(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Direction of (pins o A0) cannot be changed from \"o\" to \"i\"; direction "
|
(r"^Direction of \(pins o A0\) cannot be changed from \"o\" to \"i\"; direction "
|
||||||
"can be changed from \"io\" to \"i\", \"o\", or \"oe\", or from anything "
|
r"can be changed from \"io\" to \"i\", \"o\", or \"oe\", or from anything "
|
||||||
"to \"-\""):
|
r"to \"-\"$")):
|
||||||
user_led = self.cm.request("user_led", 0, dir="i")
|
user_led = self.cm.request("user_led", 0, dir="i")
|
||||||
|
|
||||||
def test_wrong_request_with_dir_dict(self):
|
def test_wrong_request_with_dir_dict(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Directions must be a dict, not 'i', because (resource i2c 0 (subsignal scl "
|
(r"^Directions must be a dict, not 'i', because \(resource i2c 0 \(subsignal scl "
|
||||||
"(pins o N10)) (subsignal sda (pins io N11))) "
|
r"\(pins o N10\)\) \(subsignal sda \(pins io N11\)\)\) "
|
||||||
"has subsignals"):
|
r"has subsignals$")):
|
||||||
i2c = self.cm.request("i2c", 0, dir="i")
|
i2c = self.cm.request("i2c", 0, dir="i")
|
||||||
|
|
||||||
def test_wrong_request_with_wrong_xdr(self):
|
def test_wrong_request_with_wrong_xdr(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Data rate of (pins o A0) must be a non-negative integer, not -1"):
|
r"^Data rate of \(pins o A0\) must be a non-negative integer, not -1$"):
|
||||||
user_led = self.cm.request("user_led", 0, xdr=-1)
|
user_led = self.cm.request("user_led", 0, xdr=-1)
|
||||||
|
|
||||||
def test_wrong_request_with_xdr_dict(self):
|
def test_wrong_request_with_xdr_dict(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Data rate must be a dict, not 2, because (resource i2c 0 (subsignal scl "
|
r"^Data rate must be a dict, not 2, because \(resource i2c 0 \(subsignal scl "
|
||||||
"(pins o N10)) (subsignal sda (pins io N11))) "
|
r"\(pins o N10\)\) \(subsignal sda \(pins io N11\)\)\) "
|
||||||
"has subsignals"):
|
r"has subsignals$"):
|
||||||
i2c = self.cm.request("i2c", 0, xdr=2)
|
i2c = self.cm.request("i2c", 0, xdr=2)
|
||||||
|
|
||||||
def test_wrong_clock_constraint_twice(self):
|
def test_wrong_clock_constraint_twice(self):
|
||||||
clk100 = self.cm.request("clk100")
|
clk100 = self.cm.request("clk100")
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Cannot add clock constraint on (sig clk100_0__i), which is already "
|
(r"^Cannot add clock constraint on \(sig clk100_0__i\), which is already "
|
||||||
"constrained to 100000000.0 Hz"):
|
r"constrained to 100000000\.0 Hz$")):
|
||||||
self.cm.add_clock_constraint(clk100.i, 1e6)
|
self.cm.add_clock_constraint(clk100.i, 1e6)
|
||||||
|
|
|
@ -35,18 +35,18 @@ class ShapeTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s3.signed, True)
|
self.assertEqual(s3.signed, True)
|
||||||
|
|
||||||
def test_make_wrong(self):
|
def test_make_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -1"):
|
r"^Width must be a non-negative integer, not -1$"):
|
||||||
Shape(-1)
|
Shape(-1)
|
||||||
|
|
||||||
def test_compare_wrong(self):
|
def test_compare_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not 'hi'"):
|
r"^Shapes may be compared with other Shapes and \(int, bool\) tuples, not 'hi'$"):
|
||||||
Shape(1, True) == 'hi'
|
Shape(1, True) == 'hi'
|
||||||
|
|
||||||
def test_compare_tuple_wrong(self):
|
def test_compare_tuple_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shapes may be compared with other Shapes and (int, bool) tuples, not (2, 3)"):
|
r"^Shapes may be compared with other Shapes and \(int, bool\) tuples, not \(2, 3\)$"):
|
||||||
Shape(1, True) == (2, 3)
|
Shape(1, True) == (2, 3)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
|
@ -84,8 +84,8 @@ class ShapeTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s1.signed, False)
|
self.assertEqual(s1.signed, False)
|
||||||
|
|
||||||
def test_cast_int_wrong(self):
|
def test_cast_int_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -1"):
|
r"^Width must be a non-negative integer, not -1$"):
|
||||||
Shape.cast(-1)
|
Shape.cast(-1)
|
||||||
|
|
||||||
def test_cast_tuple(self):
|
def test_cast_tuple(self):
|
||||||
|
@ -98,8 +98,8 @@ class ShapeTestCase(FHDLTestCase):
|
||||||
def test_cast_tuple_wrong(self):
|
def test_cast_tuple_wrong(self):
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
warnings.filterwarnings(action="ignore", category=DeprecationWarning)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -1"):
|
r"^Width must be a non-negative integer, not -1$"):
|
||||||
Shape.cast((-1, True))
|
Shape.cast((-1, True))
|
||||||
|
|
||||||
def test_cast_range(self):
|
def test_cast_range(self):
|
||||||
|
@ -134,13 +134,13 @@ class ShapeTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s2.signed, True)
|
self.assertEqual(s2.signed, True)
|
||||||
|
|
||||||
def test_cast_enum_bad(self):
|
def test_cast_enum_bad(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Only enumerations with integer values can be used as value shapes"):
|
r"^Only enumerations with integer values can be used as value shapes$"):
|
||||||
Shape.cast(StringEnum)
|
Shape.cast(StringEnum)
|
||||||
|
|
||||||
def test_cast_bad(self):
|
def test_cast_bad(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Object 'foo' cannot be used as value shape"):
|
r"^Object 'foo' cannot be used as value shape$"):
|
||||||
Shape.cast("foo")
|
Shape.cast("foo")
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,8 +150,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
self.assertIsInstance(Value.cast(True), Const)
|
self.assertIsInstance(Value.cast(True), Const)
|
||||||
c = Const(0)
|
c = Const(0)
|
||||||
self.assertIs(Value.cast(c), c)
|
self.assertIs(Value.cast(c), c)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Object 'str' cannot be converted to an nMigen value"):
|
r"^Object 'str' cannot be converted to an nMigen value$"):
|
||||||
Value.cast("str")
|
Value.cast("str")
|
||||||
|
|
||||||
def test_cast_enum(self):
|
def test_cast_enum(self):
|
||||||
|
@ -163,13 +163,13 @@ class ValueTestCase(FHDLTestCase):
|
||||||
self.assertEqual(e2.shape(), signed(2))
|
self.assertEqual(e2.shape(), signed(2))
|
||||||
|
|
||||||
def test_cast_enum_wrong(self):
|
def test_cast_enum_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Only enumerations with integer values can be used as value shapes"):
|
r"^Only enumerations with integer values can be used as value shapes$"):
|
||||||
Value.cast(StringEnum.FOO)
|
Value.cast(StringEnum.FOO)
|
||||||
|
|
||||||
def test_bool(self):
|
def test_bool(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Attempted to convert nMigen value to Python boolean"):
|
r"^Attempted to convert nMigen value to Python boolean$"):
|
||||||
if Const(0):
|
if Const(0):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -185,8 +185,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
self.assertIsInstance(s2, Slice)
|
self.assertIsInstance(s2, Slice)
|
||||||
self.assertEqual(s2.start, 3)
|
self.assertEqual(s2.start, 3)
|
||||||
self.assertEqual(s2.stop, 4)
|
self.assertEqual(s2.stop, 4)
|
||||||
with self.assertRaises(IndexError,
|
with self.assertRaisesRegex(IndexError,
|
||||||
msg="Cannot index 5 bits into 4-bit value"):
|
r"^Cannot index 5 bits into 4-bit value$"):
|
||||||
Const(10)[5]
|
Const(10)[5]
|
||||||
|
|
||||||
def test_getitem_slice(self):
|
def test_getitem_slice(self):
|
||||||
|
@ -211,8 +211,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s3.parts[2].stop, 5)
|
self.assertEqual(s3.parts[2].stop, 5)
|
||||||
|
|
||||||
def test_getitem_wrong(self):
|
def test_getitem_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Cannot index value with 'str'"):
|
r"^Cannot index value with 'str'$"):
|
||||||
Const(31)["str"]
|
Const(31)["str"]
|
||||||
|
|
||||||
def test_shift_left(self):
|
def test_shift_left(self):
|
||||||
|
@ -240,8 +240,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
"(s (slice (const 9'sd-256) 9:9))")
|
"(s (slice (const 9'sd-256) 9:9))")
|
||||||
|
|
||||||
def test_shift_left_wrong(self):
|
def test_shift_left_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be an integer, not 'str'"):
|
r"^Shift amount must be an integer, not 'str'$"):
|
||||||
Const(31).shift_left("str")
|
Const(31).shift_left("str")
|
||||||
|
|
||||||
def test_shift_right(self):
|
def test_shift_right(self):
|
||||||
|
@ -269,8 +269,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
"(s (slice (const 9'sd-256) 9:9))")
|
"(s (slice (const 9'sd-256) 9:9))")
|
||||||
|
|
||||||
def test_shift_right_wrong(self):
|
def test_shift_right_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be an integer, not 'str'"):
|
r"^Shift amount must be an integer, not 'str'$"):
|
||||||
Const(31).shift_left("str")
|
Const(31).shift_left("str")
|
||||||
|
|
||||||
def test_rotate_left(self):
|
def test_rotate_left(self):
|
||||||
|
@ -284,8 +284,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
"(cat (slice (const 9'd256) 7:9) (slice (const 9'd256) 0:7))")
|
"(cat (slice (const 9'd256) 7:9) (slice (const 9'd256) 0:7))")
|
||||||
|
|
||||||
def test_rotate_left_wrong(self):
|
def test_rotate_left_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Rotate amount must be an integer, not 'str'"):
|
r"^Rotate amount must be an integer, not 'str'$"):
|
||||||
Const(31).rotate_left("str")
|
Const(31).rotate_left("str")
|
||||||
|
|
||||||
def test_rotate_right(self):
|
def test_rotate_right(self):
|
||||||
|
@ -299,8 +299,8 @@ class ValueTestCase(FHDLTestCase):
|
||||||
"(cat (slice (const 9'd256) 2:9) (slice (const 9'd256) 0:2))")
|
"(cat (slice (const 9'd256) 2:9) (slice (const 9'd256) 0:2))")
|
||||||
|
|
||||||
def test_rotate_right_wrong(self):
|
def test_rotate_right_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Rotate amount must be an integer, not 'str'"):
|
r"^Rotate amount must be an integer, not 'str'$"):
|
||||||
Const(31).rotate_right("str")
|
Const(31).rotate_right("str")
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,8 +318,8 @@ class ConstTestCase(FHDLTestCase):
|
||||||
self.assertEqual(Const(0, unsigned(0)).shape(), unsigned(0))
|
self.assertEqual(Const(0, unsigned(0)).shape(), unsigned(0))
|
||||||
|
|
||||||
def test_shape_wrong(self):
|
def test_shape_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -1"):
|
r"^Width must be a non-negative integer, not -1$"):
|
||||||
Const(1, -1)
|
Const(1, -1)
|
||||||
|
|
||||||
def test_normalization(self):
|
def test_normalization(self):
|
||||||
|
@ -413,8 +413,8 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(v5.shape(), unsigned(4))
|
self.assertEqual(v5.shape(), unsigned(4))
|
||||||
|
|
||||||
def test_mod_wrong(self):
|
def test_mod_wrong(self):
|
||||||
with self.assertRaises(NotImplementedError,
|
with self.assertRaisesRegex(NotImplementedError,
|
||||||
msg="Division by a signed value is not supported"):
|
r"^Division by a signed value is not supported$"):
|
||||||
Const(0, signed(4)) % Const(0, signed(6))
|
Const(0, signed(4)) % Const(0, signed(6))
|
||||||
|
|
||||||
def test_floordiv(self):
|
def test_floordiv(self):
|
||||||
|
@ -427,8 +427,8 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(v5.shape(), unsigned(4))
|
self.assertEqual(v5.shape(), unsigned(4))
|
||||||
|
|
||||||
def test_floordiv_wrong(self):
|
def test_floordiv_wrong(self):
|
||||||
with self.assertRaises(NotImplementedError,
|
with self.assertRaisesRegex(NotImplementedError,
|
||||||
msg="Division by a signed value is not supported"):
|
r"^Division by a signed value is not supported$"):
|
||||||
Const(0, signed(4)) // Const(0, signed(6))
|
Const(0, signed(4)) // Const(0, signed(6))
|
||||||
|
|
||||||
def test_and(self):
|
def test_and(self):
|
||||||
|
@ -476,11 +476,11 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(v1.shape(), unsigned(11))
|
self.assertEqual(v1.shape(), unsigned(11))
|
||||||
|
|
||||||
def test_shl_wrong(self):
|
def test_shl_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be unsigned"):
|
r"^Shift amount must be unsigned$"):
|
||||||
1 << Const(0, signed(6))
|
1 << Const(0, signed(6))
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be unsigned"):
|
r"^Shift amount must be unsigned$"):
|
||||||
Const(1, unsigned(4)) << -1
|
Const(1, unsigned(4)) << -1
|
||||||
|
|
||||||
def test_shr(self):
|
def test_shr(self):
|
||||||
|
@ -489,11 +489,11 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
self.assertEqual(v1.shape(), unsigned(4))
|
self.assertEqual(v1.shape(), unsigned(4))
|
||||||
|
|
||||||
def test_shr_wrong(self):
|
def test_shr_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be unsigned"):
|
r"^Shift amount must be unsigned$"):
|
||||||
1 << Const(0, signed(6))
|
1 << Const(0, signed(6))
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Shift amount must be unsigned"):
|
r"^Shift amount must be unsigned$"):
|
||||||
Const(1, unsigned(4)) << -1
|
Const(1, unsigned(4)) << -1
|
||||||
|
|
||||||
def test_lt(self):
|
def test_lt(self):
|
||||||
|
@ -588,25 +588,25 @@ class OperatorTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_matches_width_wrong(self):
|
def test_matches_width_wrong(self):
|
||||||
s = Signal(4)
|
s = Signal(4)
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Match pattern '--' must have the same width as match value (which is 4)"):
|
r"^Match pattern '--' must have the same width as match value \(which is 4\)$"):
|
||||||
s.matches("--")
|
s.matches("--")
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Match pattern '10110' is wider than match value (which has width 4); "
|
(r"^Match pattern '10110' is wider than match value \(which has width 4\); "
|
||||||
"comparison will never be true"):
|
r"comparison will never be true$")):
|
||||||
s.matches(0b10110)
|
s.matches(0b10110)
|
||||||
|
|
||||||
def test_matches_bits_wrong(self):
|
def test_matches_bits_wrong(self):
|
||||||
s = Signal(4)
|
s = Signal(4)
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Match pattern 'abc' must consist of 0, 1, and - (don't care) bits, "
|
(r"^Match pattern 'abc' must consist of 0, 1, and - \(don't care\) bits, "
|
||||||
"and may include whitespace"):
|
r"and may include whitespace$")):
|
||||||
s.matches("abc")
|
s.matches("abc")
|
||||||
|
|
||||||
def test_matches_pattern_wrong(self):
|
def test_matches_pattern_wrong(self):
|
||||||
s = Signal(4)
|
s = Signal(4)
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Match pattern must be an integer, a string, or an enumeration, not 1.0"):
|
r"^Match pattern must be an integer, a string, or an enumeration, not 1\.0$"):
|
||||||
s.matches(1.0)
|
s.matches(1.0)
|
||||||
|
|
||||||
def test_hash(self):
|
def test_hash(self):
|
||||||
|
@ -630,23 +630,23 @@ class SliceTestCase(FHDLTestCase):
|
||||||
self.assertEqual((s1.start, s1.stop), (4, 7))
|
self.assertEqual((s1.start, s1.stop), (4, 7))
|
||||||
|
|
||||||
def test_start_end_wrong(self):
|
def test_start_end_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Slice start must be an integer, not 'x'"):
|
r"^Slice start must be an integer, not 'x'$"):
|
||||||
Slice(0, "x", 1)
|
Slice(0, "x", 1)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Slice stop must be an integer, not 'x'"):
|
r"^Slice stop must be an integer, not 'x'$"):
|
||||||
Slice(0, 1, "x")
|
Slice(0, 1, "x")
|
||||||
|
|
||||||
def test_start_end_out_of_range(self):
|
def test_start_end_out_of_range(self):
|
||||||
c = Const(0, 8)
|
c = Const(0, 8)
|
||||||
with self.assertRaises(IndexError,
|
with self.assertRaisesRegex(IndexError,
|
||||||
msg="Cannot start slice 10 bits into 8-bit value"):
|
r"^Cannot start slice 10 bits into 8-bit value$"):
|
||||||
Slice(c, 10, 12)
|
Slice(c, 10, 12)
|
||||||
with self.assertRaises(IndexError,
|
with self.assertRaisesRegex(IndexError,
|
||||||
msg="Cannot stop slice 12 bits into 8-bit value"):
|
r"^Cannot stop slice 12 bits into 8-bit value$"):
|
||||||
Slice(c, 0, 12)
|
Slice(c, 0, 12)
|
||||||
with self.assertRaises(IndexError,
|
with self.assertRaisesRegex(IndexError,
|
||||||
msg="Slice start 4 must be less than slice stop 2"):
|
r"^Slice start 4 must be less than slice stop 2$"):
|
||||||
Slice(c, 4, 2)
|
Slice(c, 4, 2)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
|
@ -842,8 +842,8 @@ class SignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(s11.shape(), unsigned(1))
|
self.assertEqual(s11.shape(), unsigned(1))
|
||||||
|
|
||||||
def test_shape_wrong(self):
|
def test_shape_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Width must be a non-negative integer, not -10"):
|
r"^Width must be a non-negative integer, not -10$"):
|
||||||
Signal(-10)
|
Signal(-10)
|
||||||
|
|
||||||
def test_name(self):
|
def test_name(self):
|
||||||
|
@ -860,20 +860,20 @@ class SignalTestCase(FHDLTestCase):
|
||||||
def test_reset_enum(self):
|
def test_reset_enum(self):
|
||||||
s1 = Signal(2, reset=UnsignedEnum.BAR)
|
s1 = Signal(2, reset=UnsignedEnum.BAR)
|
||||||
self.assertEqual(s1.reset, 2)
|
self.assertEqual(s1.reset, 2)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Reset value has to be an int or an integral Enum"
|
r"^Reset value has to be an int or an integral Enum$"
|
||||||
):
|
):
|
||||||
Signal(1, reset=StringEnum.FOO)
|
Signal(1, reset=StringEnum.FOO)
|
||||||
|
|
||||||
def test_reset_narrow(self):
|
def test_reset_narrow(self):
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Reset value 8 requires 4 bits to represent, but the signal only has 3 bits"):
|
r"^Reset value 8 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||||
Signal(3, reset=8)
|
Signal(3, reset=8)
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Reset value 4 requires 4 bits to represent, but the signal only has 3 bits"):
|
r"^Reset value 4 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||||
Signal(signed(3), reset=4)
|
Signal(signed(3), reset=4)
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Reset value -5 requires 4 bits to represent, but the signal only has 3 bits"):
|
r"^Reset value -5 requires 4 bits to represent, but the signal only has 3 bits$"):
|
||||||
Signal(signed(3), reset=-5)
|
Signal(signed(3), reset=-5)
|
||||||
|
|
||||||
def test_attrs(self):
|
def test_attrs(self):
|
||||||
|
@ -928,8 +928,8 @@ class ClockSignalTestCase(FHDLTestCase):
|
||||||
s2 = ClockSignal("pix")
|
s2 = ClockSignal("pix")
|
||||||
self.assertEqual(s2.domain, "pix")
|
self.assertEqual(s2.domain, "pix")
|
||||||
|
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Clock domain name must be a string, not 1"):
|
r"^Clock domain name must be a string, not 1$"):
|
||||||
ClockSignal(1)
|
ClockSignal(1)
|
||||||
|
|
||||||
def test_shape(self):
|
def test_shape(self):
|
||||||
|
@ -942,8 +942,8 @@ class ClockSignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(repr(s1), "(clk sync)")
|
self.assertEqual(repr(s1), "(clk sync)")
|
||||||
|
|
||||||
def test_wrong_name_comb(self):
|
def test_wrong_name_comb(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'comb' does not have a clock"):
|
r"^Domain 'comb' does not have a clock$"):
|
||||||
ClockSignal("comb")
|
ClockSignal("comb")
|
||||||
|
|
||||||
|
|
||||||
|
@ -954,8 +954,8 @@ class ResetSignalTestCase(FHDLTestCase):
|
||||||
s2 = ResetSignal("pix")
|
s2 = ResetSignal("pix")
|
||||||
self.assertEqual(s2.domain, "pix")
|
self.assertEqual(s2.domain, "pix")
|
||||||
|
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Clock domain name must be a string, not 1"):
|
r"^Clock domain name must be a string, not 1$"):
|
||||||
ResetSignal(1)
|
ResetSignal(1)
|
||||||
|
|
||||||
def test_shape(self):
|
def test_shape(self):
|
||||||
|
@ -968,8 +968,8 @@ class ResetSignalTestCase(FHDLTestCase):
|
||||||
self.assertEqual(repr(s1), "(rst sync)")
|
self.assertEqual(repr(s1), "(rst sync)")
|
||||||
|
|
||||||
def test_wrong_name_comb(self):
|
def test_wrong_name_comb(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'comb' does not have a reset"):
|
r"^Domain 'comb' does not have a reset$"):
|
||||||
ResetSignal("comb")
|
ResetSignal("comb")
|
||||||
|
|
||||||
|
|
||||||
|
@ -1014,19 +1014,19 @@ class SampleTestCase(FHDLTestCase):
|
||||||
s3 = Sample(ResetSignal(), 1, "sync")
|
s3 = Sample(ResetSignal(), 1, "sync")
|
||||||
|
|
||||||
def test_wrong_value_operator(self):
|
def test_wrong_value_operator(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
"Sampled value must be a signal or a constant, not "
|
(r"^Sampled value must be a signal or a constant, not "
|
||||||
"(+ (sig $signal) (const 1'd1))"):
|
r"\(\+ \(sig \$signal\) \(const 1'd1\)\)$")):
|
||||||
Sample(Signal() + 1, 1, "sync")
|
Sample(Signal() + 1, 1, "sync")
|
||||||
|
|
||||||
def test_wrong_clocks_neg(self):
|
def test_wrong_clocks_neg(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
"Cannot sample a value 1 cycles in the future"):
|
r"^Cannot sample a value 1 cycles in the future$"):
|
||||||
Sample(Signal(), -1, "sync")
|
Sample(Signal(), -1, "sync")
|
||||||
|
|
||||||
def test_wrong_domain(self):
|
def test_wrong_domain(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
"Domain name must be a string or None, not 0"):
|
r"^Domain name must be a string or None, not 0$"):
|
||||||
Sample(Signal(), 1, 0)
|
Sample(Signal(), 1, 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ class ClockDomainTestCase(FHDLTestCase):
|
||||||
self.assertEqual(pix.name, "pix")
|
self.assertEqual(pix.name, "pix")
|
||||||
dom = [ClockDomain("foo")][0]
|
dom = [ClockDomain("foo")][0]
|
||||||
self.assertEqual(dom.name, "foo")
|
self.assertEqual(dom.name, "foo")
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Clock domain name must be specified explicitly"):
|
r"^Clock domain name must be specified explicitly$"):
|
||||||
ClockDomain()
|
ClockDomain()
|
||||||
cd_reset = ClockDomain(local=True)
|
cd_reset = ClockDomain(local=True)
|
||||||
self.assertEqual(cd_reset.local, True)
|
self.assertEqual(cd_reset.local, True)
|
||||||
|
@ -32,8 +32,8 @@ class ClockDomainTestCase(FHDLTestCase):
|
||||||
self.assertEqual(sync.clk_edge, "neg")
|
self.assertEqual(sync.clk_edge, "neg")
|
||||||
|
|
||||||
def test_edge_wrong(self):
|
def test_edge_wrong(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain clock edge must be one of 'pos' or 'neg', not 'xxx'"):
|
r"^Domain clock edge must be one of 'pos' or 'neg', not 'xxx'$"):
|
||||||
ClockDomain("sync", clk_edge="xxx")
|
ClockDomain("sync", clk_edge="xxx")
|
||||||
|
|
||||||
def test_with_reset(self):
|
def test_with_reset(self):
|
||||||
|
@ -73,6 +73,6 @@ class ClockDomainTestCase(FHDLTestCase):
|
||||||
self.assertEqual(sync.clk.name, "pix_clk")
|
self.assertEqual(sync.clk.name, "pix_clk")
|
||||||
|
|
||||||
def test_wrong_name_comb(self):
|
def test_wrong_name_comb(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'comb' may not be clocked"):
|
r"^Domain 'comb' may not be clocked$"):
|
||||||
comb = ClockDomain()
|
comb = ClockDomain()
|
||||||
|
|
|
@ -20,9 +20,9 @@ class DSLTestCase(FHDLTestCase):
|
||||||
self.w1 = Signal(4)
|
self.w1 = Signal(4)
|
||||||
|
|
||||||
def test_cant_inherit(self):
|
def test_cant_inherit(self):
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Instead of inheriting from `Module`, inherit from `Elaboratable` and "
|
(r"^Instead of inheriting from `Module`, inherit from `Elaboratable` and "
|
||||||
"return a `Module` from the `elaborate(self, platform)` method"):
|
r"return a `Module` from the `elaborate\(self, platform\)` method$")):
|
||||||
class ORGate(Module):
|
class ORGate(Module):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -69,47 +69,47 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_d_conflict(self):
|
def test_d_conflict(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Driver-driver conflict: trying to drive (sig c1) from d.sync, but it "
|
(r"^Driver-driver conflict: trying to drive \(sig c1\) from d\.sync, but it "
|
||||||
"is already driven from d.comb"):
|
r"is already driven from d\.comb$")):
|
||||||
m.d.comb += self.c1.eq(1)
|
m.d.comb += self.c1.eq(1)
|
||||||
m.d.sync += self.c1.eq(1)
|
m.d.sync += self.c1.eq(1)
|
||||||
|
|
||||||
def test_d_wrong(self):
|
def test_d_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Cannot assign 'd.pix' attribute; did you mean 'd.pix +='?"):
|
r"^Cannot assign 'd\.pix' attribute; did you mean 'd.pix \+='\?$"):
|
||||||
m.d.pix = None
|
m.d.pix = None
|
||||||
|
|
||||||
def test_d_asgn_wrong(self):
|
def test_d_asgn_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Only assignments and property checks may be appended to d.sync"):
|
r"^Only assignments and property checks may be appended to d\.sync$"):
|
||||||
m.d.sync += Switch(self.s1, {})
|
m.d.sync += Switch(self.s1, {})
|
||||||
|
|
||||||
def test_comb_wrong(self):
|
def test_comb_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="'Module' object has no attribute 'comb'; did you mean 'd.comb'?"):
|
r"^'Module' object has no attribute 'comb'; did you mean 'd\.comb'\?$"):
|
||||||
m.comb += self.c1.eq(1)
|
m.comb += self.c1.eq(1)
|
||||||
|
|
||||||
def test_sync_wrong(self):
|
def test_sync_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="'Module' object has no attribute 'sync'; did you mean 'd.sync'?"):
|
r"^'Module' object has no attribute 'sync'; did you mean 'd\.sync'\?$"):
|
||||||
m.sync += self.c1.eq(1)
|
m.sync += self.c1.eq(1)
|
||||||
|
|
||||||
def test_attr_wrong(self):
|
def test_attr_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="'Module' object has no attribute 'nonexistentattr'"):
|
r"^'Module' object has no attribute 'nonexistentattr'$"):
|
||||||
m.nonexistentattr
|
m.nonexistentattr
|
||||||
|
|
||||||
def test_d_suspicious(self):
|
def test_d_suspicious(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Using '<module>.d.submodules' would add statements to clock domain "
|
(r"^Using '<module>\.d\.submodules' would add statements to clock domain "
|
||||||
"'submodules'; did you mean <module>.submodules instead?"):
|
r"'submodules'; did you mean <module>\.submodules instead\?$")):
|
||||||
m.d.submodules += []
|
m.d.submodules += []
|
||||||
|
|
||||||
def test_clock_signal(self):
|
def test_clock_signal(self):
|
||||||
|
@ -260,15 +260,15 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_Elif_wrong(self):
|
def test_Elif_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Elif without preceding If"):
|
r"^Elif without preceding If$"):
|
||||||
with m.Elif(self.s2):
|
with m.Elif(self.s2):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_Else_wrong(self):
|
def test_Else_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Else without preceding If/Elif"):
|
r"^Else without preceding If\/Elif$"):
|
||||||
with m.Else():
|
with m.Else():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -287,11 +287,11 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_If_signed_suspicious(self):
|
def test_If_signed_suspicious(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Signed values in If/Elif conditions usually result from inverting Python "
|
(r"^Signed values in If\/Elif conditions usually result from inverting Python "
|
||||||
"booleans with ~, which leads to unexpected results. Replace `~flag` with "
|
r"booleans with ~, which leads to unexpected results\. Replace `~flag` with "
|
||||||
"`not flag`. (If this is a false positive, silence this warning with "
|
r"`not flag`\. \(If this is a false positive, silence this warning with "
|
||||||
"`m.If(x)` → `m.If(x.bool())`.)"):
|
r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")):
|
||||||
with m.If(~True):
|
with m.If(~True):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -299,28 +299,28 @@ class DSLTestCase(FHDLTestCase):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.If(0):
|
with m.If(0):
|
||||||
pass
|
pass
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Signed values in If/Elif conditions usually result from inverting Python "
|
(r"^Signed values in If\/Elif conditions usually result from inverting Python "
|
||||||
"booleans with ~, which leads to unexpected results. Replace `~flag` with "
|
r"booleans with ~, which leads to unexpected results\. Replace `~flag` with "
|
||||||
"`not flag`. (If this is a false positive, silence this warning with "
|
r"`not flag`\. \(If this is a false positive, silence this warning with "
|
||||||
"`m.If(x)` → `m.If(x.bool())`.)"):
|
r"`m\.If\(x\)` → `m\.If\(x\.bool\(\)\)`\.\)$")):
|
||||||
with m.Elif(~True):
|
with m.Elif(~True):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_if_If_Elif_Else(self):
|
def test_if_If_Elif_Else(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="`if m.If(...):` does not work; use `with m.If(...)`"):
|
r"^`if m\.If\(\.\.\.\):` does not work; use `with m\.If\(\.\.\.\)`$"):
|
||||||
if m.If(0):
|
if m.If(0):
|
||||||
pass
|
pass
|
||||||
with m.If(0):
|
with m.If(0):
|
||||||
pass
|
pass
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="`if m.Elif(...):` does not work; use `with m.Elif(...)`"):
|
r"^`if m\.Elif\(\.\.\.\):` does not work; use `with m\.Elif\(\.\.\.\)`$"):
|
||||||
if m.Elif(0):
|
if m.Elif(0):
|
||||||
pass
|
pass
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="`if m.Else(...):` does not work; use `with m.Else(...)`"):
|
r"^`if m\.Else\(\.\.\.\):` does not work; use `with m\.Else\(\.\.\.\)`$"):
|
||||||
if m.Else():
|
if m.Else():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -414,18 +414,18 @@ class DSLTestCase(FHDLTestCase):
|
||||||
RED = 0b10101010
|
RED = 0b10101010
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.Switch(self.w1):
|
with m.Switch(self.w1):
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Case pattern '--' must have the same width as switch value (which is 4)"):
|
r"^Case pattern '--' must have the same width as switch value \(which is 4\)$"):
|
||||||
with m.Case("--"):
|
with m.Case("--"):
|
||||||
pass
|
pass
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Case pattern '10110' is wider than switch value (which has width 4); "
|
(r"^Case pattern '10110' is wider than switch value \(which has width 4\); "
|
||||||
"comparison will never be true"):
|
r"comparison will never be true$")):
|
||||||
with m.Case(0b10110):
|
with m.Case(0b10110):
|
||||||
pass
|
pass
|
||||||
with self.assertWarns(SyntaxWarning,
|
with self.assertWarnsRegex(SyntaxWarning,
|
||||||
msg="Case pattern '10101010' (Color.RED) is wider than switch value "
|
(r"^Case pattern '10101010' \(Color\.RED\) is wider than switch value "
|
||||||
"(which has width 4); comparison will never be true"):
|
r"\(which has width 4\); comparison will never be true$")):
|
||||||
with m.Case(Color.RED):
|
with m.Case(Color.RED):
|
||||||
pass
|
pass
|
||||||
self.assertRepr(m._statements, """
|
self.assertRepr(m._statements, """
|
||||||
|
@ -437,33 +437,33 @@ class DSLTestCase(FHDLTestCase):
|
||||||
def test_Case_bits_wrong(self):
|
def test_Case_bits_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.Switch(self.w1):
|
with m.Switch(self.w1):
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Case pattern 'abc' must consist of 0, 1, and - (don't care) bits, "
|
(r"^Case pattern 'abc' must consist of 0, 1, and - \(don't care\) bits, "
|
||||||
"and may include whitespace"):
|
r"and may include whitespace$")):
|
||||||
with m.Case("abc"):
|
with m.Case("abc"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_Case_pattern_wrong(self):
|
def test_Case_pattern_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.Switch(self.w1):
|
with m.Switch(self.w1):
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Case pattern must be an integer, a string, or an enumeration, not 1.0"):
|
r"^Case pattern must be an integer, a string, or an enumeration, not 1\.0$"):
|
||||||
with m.Case(1.0):
|
with m.Case(1.0):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_Case_outside_Switch_wrong(self):
|
def test_Case_outside_Switch_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Case is not permitted outside of Switch"):
|
r"^Case is not permitted outside of Switch$"):
|
||||||
with m.Case():
|
with m.Case():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_If_inside_Switch_wrong(self):
|
def test_If_inside_Switch_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with m.Switch(self.s1):
|
with m.Switch(self.s1):
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="If is not permitted directly inside of Switch; "
|
(r"^If is not permitted directly inside of Switch; "
|
||||||
"it is permitted inside of Switch Case"):
|
r"it is permitted inside of Switch Case$")):
|
||||||
with m.If(self.s2):
|
with m.If(self.s2):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -577,15 +577,15 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_FSM_wrong_domain(self):
|
def test_FSM_wrong_domain(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="FSM may not be driven by the 'comb' domain"):
|
r"^FSM may not be driven by the 'comb' domain$"):
|
||||||
with m.FSM(domain="comb"):
|
with m.FSM(domain="comb"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_FSM_wrong_undefined(self):
|
def test_FSM_wrong_undefined(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="FSM state 'FOO' is referenced but not defined"):
|
r"^FSM state 'FOO' is referenced but not defined$"):
|
||||||
with m.FSM() as fsm:
|
with m.FSM() as fsm:
|
||||||
fsm.ongoing("FOO")
|
fsm.ongoing("FOO")
|
||||||
|
|
||||||
|
@ -594,21 +594,21 @@ class DSLTestCase(FHDLTestCase):
|
||||||
with m.FSM():
|
with m.FSM():
|
||||||
with m.State("FOO"):
|
with m.State("FOO"):
|
||||||
pass
|
pass
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="FSM state 'FOO' is already defined"):
|
r"^FSM state 'FOO' is already defined$"):
|
||||||
with m.State("FOO"):
|
with m.State("FOO"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_FSM_wrong_next(self):
|
def test_FSM_wrong_next(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="Only assignment to `m.next` is permitted"):
|
r"^Only assignment to `m\.next` is permitted$"):
|
||||||
m.next
|
m.next
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="`m.next = <...>` is only permitted inside an FSM state"):
|
r"^`m\.next = <\.\.\.>` is only permitted inside an FSM state$"):
|
||||||
m.next = "FOO"
|
m.next = "FOO"
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="`m.next = <...>` is only permitted inside an FSM state"):
|
r"^`m\.next = <\.\.\.>` is only permitted inside an FSM state$"):
|
||||||
with m.FSM():
|
with m.FSM():
|
||||||
m.next = "FOO"
|
m.next = "FOO"
|
||||||
|
|
||||||
|
@ -617,9 +617,9 @@ class DSLTestCase(FHDLTestCase):
|
||||||
with m.FSM():
|
with m.FSM():
|
||||||
with m.State("FOO"):
|
with m.State("FOO"):
|
||||||
pass
|
pass
|
||||||
with self.assertRaises(SyntaxError,
|
with self.assertRaisesRegex(SyntaxError,
|
||||||
msg="If is not permitted directly inside of FSM; "
|
(r"^If is not permitted directly inside of FSM; "
|
||||||
"it is permitted inside of FSM State"):
|
r"it is permitted inside of FSM State$")):
|
||||||
with m.If(self.s2):
|
with m.If(self.s2):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -668,18 +668,18 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_submodule_wrong(self):
|
def test_submodule_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Trying to add 1, which does not implement .elaborate(), as a submodule"):
|
r"^Trying to add 1, which does not implement \.elaborate\(\), as a submodule$"):
|
||||||
m.submodules.foo = 1
|
m.submodules.foo = 1
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Trying to add 1, which does not implement .elaborate(), as a submodule"):
|
r"^Trying to add 1, which does not implement \.elaborate\(\), as a submodule$"):
|
||||||
m.submodules += 1
|
m.submodules += 1
|
||||||
|
|
||||||
def test_submodule_named_conflict(self):
|
def test_submodule_named_conflict(self):
|
||||||
m1 = Module()
|
m1 = Module()
|
||||||
m2 = Module()
|
m2 = Module()
|
||||||
m1.submodules.foo = m2
|
m1.submodules.foo = m2
|
||||||
with self.assertRaises(NameError, msg="Submodule named 'foo' already exists"):
|
with self.assertRaisesRegex(NameError, r"^Submodule named 'foo' already exists$"):
|
||||||
m1.submodules.foo = m2
|
m1.submodules.foo = m2
|
||||||
|
|
||||||
def test_submodule_get(self):
|
def test_submodule_get(self):
|
||||||
|
@ -698,9 +698,9 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_submodule_get_unset(self):
|
def test_submodule_get_unset(self):
|
||||||
m1 = Module()
|
m1 = Module()
|
||||||
with self.assertRaises(AttributeError, msg="No submodule named 'foo' exists"):
|
with self.assertRaisesRegex(AttributeError, r"^No submodule named 'foo' exists$"):
|
||||||
m2 = m1.submodules.foo
|
m2 = m1.submodules.foo
|
||||||
with self.assertRaises(AttributeError, msg="No submodule named 'foo' exists"):
|
with self.assertRaisesRegex(AttributeError, r"^No submodule named 'foo' exists$"):
|
||||||
m2 = m1.submodules["foo"]
|
m2 = m1.submodules["foo"]
|
||||||
|
|
||||||
def test_domain_named_implicit(self):
|
def test_domain_named_implicit(self):
|
||||||
|
@ -716,24 +716,24 @@ class DSLTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_domain_add_wrong(self):
|
def test_domain_add_wrong(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Only clock domains may be added to `m.domains`, not 1"):
|
r"^Only clock domains may be added to `m\.domains`, not 1$"):
|
||||||
m.domains.foo = 1
|
m.domains.foo = 1
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Only clock domains may be added to `m.domains`, not 1"):
|
r"^Only clock domains may be added to `m\.domains`, not 1$"):
|
||||||
m.domains += 1
|
m.domains += 1
|
||||||
|
|
||||||
def test_domain_add_wrong_name(self):
|
def test_domain_add_wrong_name(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Clock domain name 'bar' must match name in `m.domains.foo += ...` syntax"):
|
r"^Clock domain name 'bar' must match name in `m\.domains\.foo \+= \.\.\.` syntax$"):
|
||||||
m.domains.foo = ClockDomain("bar")
|
m.domains.foo = ClockDomain("bar")
|
||||||
|
|
||||||
def test_domain_add_wrong_duplicate(self):
|
def test_domain_add_wrong_duplicate(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
m.domains += ClockDomain("foo")
|
m.domains += ClockDomain("foo")
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Clock domain named 'foo' already exists"):
|
r"^Clock domain named 'foo' already exists$"):
|
||||||
m.domains += ClockDomain("foo")
|
m.domains += ClockDomain("foo")
|
||||||
|
|
||||||
def test_lower(self):
|
def test_lower(self):
|
||||||
|
|
|
@ -16,14 +16,14 @@ class BadElaboratable(Elaboratable):
|
||||||
|
|
||||||
class FragmentGetTestCase(FHDLTestCase):
|
class FragmentGetTestCase(FHDLTestCase):
|
||||||
def test_get_wrong(self):
|
def test_get_wrong(self):
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Object None cannot be elaborated"):
|
r"^Object None cannot be elaborated$"):
|
||||||
Fragment.get(None, platform=None)
|
Fragment.get(None, platform=None)
|
||||||
|
|
||||||
with self.assertWarns(UserWarning,
|
with self.assertWarnsRegex(UserWarning,
|
||||||
msg=".elaborate() returned None; missing return statement?"):
|
r"^\.elaborate\(\) returned None; missing return statement\?$"):
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Object None cannot be elaborated"):
|
r"^Object None cannot be elaborated$"):
|
||||||
Fragment.get(BadElaboratable(), platform=None)
|
Fragment.get(BadElaboratable(), platform=None)
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ class FragmentGeneratedTestCase(FHDLTestCase):
|
||||||
f2 = Fragment()
|
f2 = Fragment()
|
||||||
f1.add_subfragment(f2, "f2")
|
f1.add_subfragment(f2, "f2")
|
||||||
|
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="No subfragment at index #1"):
|
r"^No subfragment at index #1$"):
|
||||||
f1.find_subfragment(1)
|
f1.find_subfragment(1)
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="No subfragment with name 'fx'"):
|
r"^No subfragment with name 'fx'$"):
|
||||||
f1.find_subfragment("fx")
|
f1.find_subfragment("fx")
|
||||||
|
|
||||||
def test_find_generated(self):
|
def test_find_generated(self):
|
||||||
|
@ -300,18 +300,18 @@ class FragmentPortsTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_port_wrong(self):
|
def test_port_wrong(self):
|
||||||
f = Fragment()
|
f = Fragment()
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Only signals may be added as ports, not (const 1'd1)"):
|
r"^Only signals may be added as ports, not \(const 1'd1\)$"):
|
||||||
f.prepare(ports=(Const(1),))
|
f.prepare(ports=(Const(1),))
|
||||||
|
|
||||||
def test_port_not_iterable(self):
|
def test_port_not_iterable(self):
|
||||||
f = Fragment()
|
f = Fragment()
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="`ports` must be either a list or a tuple, not 1"):
|
r"^`ports` must be either a list or a tuple, not 1$"):
|
||||||
f.prepare(ports=1)
|
f.prepare(ports=1)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="`ports` must be either a list or a tuple, not (const 1'd1)" +
|
(r"^`ports` must be either a list or a tuple, not \(const 1'd1\)"
|
||||||
" (did you mean `ports=(<signal>,)`, rather than `ports=<signal>`?)"):
|
r" \(did you mean `ports=\(<signal>,\)`, rather than `ports=<signal>`\?\)$")):
|
||||||
f.prepare(ports=Const(1))
|
f.prepare(ports=Const(1))
|
||||||
|
|
||||||
class FragmentDomainsTestCase(FHDLTestCase):
|
class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
|
@ -380,10 +380,10 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
f.add_subfragment(fa, "a")
|
f.add_subfragment(fa, "a")
|
||||||
f.add_subfragment(fb)
|
f.add_subfragment(fb)
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
|
(r"^Domain 'sync' is defined by subfragments 'a', <unnamed #1> of fragment "
|
||||||
"'top'; it is necessary to either rename subfragment domains explicitly, "
|
r"'top'; it is necessary to either rename subfragment domains explicitly, "
|
||||||
"or give names to subfragments"):
|
r"or give names to subfragments$")):
|
||||||
f._propagate_domains_up()
|
f._propagate_domains_up()
|
||||||
|
|
||||||
def test_domain_conflict_name(self):
|
def test_domain_conflict_name(self):
|
||||||
|
@ -398,10 +398,10 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
f.add_subfragment(fa, "x")
|
f.add_subfragment(fa, "x")
|
||||||
f.add_subfragment(fb, "x")
|
f.add_subfragment(fb, "x")
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
|
(r"^Domain 'sync' is defined by subfragments #0, #1 of fragment 'top', some "
|
||||||
"of which have identical names; it is necessary to either rename subfragment "
|
r"of which have identical names; it is necessary to either rename subfragment "
|
||||||
"domains explicitly, or give distinct names to subfragments"):
|
r"domains explicitly, or give distinct names to subfragments$")):
|
||||||
f._propagate_domains_up()
|
f._propagate_domains_up()
|
||||||
|
|
||||||
def test_domain_conflict_rename_drivers(self):
|
def test_domain_conflict_rename_drivers(self):
|
||||||
|
@ -481,8 +481,8 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
f1 = Fragment()
|
f1 = Fragment()
|
||||||
f1.add_driver(s1, "sync")
|
f1.add_driver(s1, "sync")
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Domain 'sync' is used but not defined"):
|
r"^Domain 'sync' is used but not defined$"):
|
||||||
f1._propagate_domains(missing_domain=lambda name: None)
|
f1._propagate_domains(missing_domain=lambda name: None)
|
||||||
|
|
||||||
def test_propagate_create_missing(self):
|
def test_propagate_create_missing(self):
|
||||||
|
@ -542,9 +542,9 @@ class FragmentDomainsTestCase(FHDLTestCase):
|
||||||
f2 = Fragment()
|
f2 = Fragment()
|
||||||
f2.add_domains(ClockDomain("foo"))
|
f2.add_domains(ClockDomain("foo"))
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Fragment returned by missing domain callback does not define requested "
|
(r"^Fragment returned by missing domain callback does not define requested "
|
||||||
"domain 'sync' (defines 'foo')."):
|
r"domain 'sync' \(defines 'foo'\)\.$")):
|
||||||
f1._propagate_domains(missing_domain=lambda name: f2)
|
f1._propagate_domains(missing_domain=lambda name: f2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -597,16 +597,16 @@ class FragmentHierarchyConflictTestCase(FHDLTestCase):
|
||||||
def test_conflict_self_sub_error(self):
|
def test_conflict_self_sub_error(self):
|
||||||
self.setUp_self_sub()
|
self.setUp_self_sub()
|
||||||
|
|
||||||
with self.assertRaises(DriverConflict,
|
with self.assertRaisesRegex(DriverConflict,
|
||||||
msg="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>"):
|
r"^Signal '\(sig s1\)' is driven from multiple fragments: top, top.<unnamed #1>$"):
|
||||||
self.f1._resolve_hierarchy_conflicts(mode="error")
|
self.f1._resolve_hierarchy_conflicts(mode="error")
|
||||||
|
|
||||||
def test_conflict_self_sub_warning(self):
|
def test_conflict_self_sub_warning(self):
|
||||||
self.setUp_self_sub()
|
self.setUp_self_sub()
|
||||||
|
|
||||||
with self.assertWarns(DriverConflict,
|
with self.assertWarnsRegex(DriverConflict,
|
||||||
msg="Signal '(sig s1)' is driven from multiple fragments: top, top.<unnamed #1>; "
|
(r"^Signal '\(sig s1\)' is driven from multiple fragments: top, top.<unnamed #1>; "
|
||||||
"hierarchy will be flattened"):
|
r"hierarchy will be flattened$")):
|
||||||
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
||||||
|
|
||||||
def setUp_sub_sub(self):
|
def setUp_sub_sub(self):
|
||||||
|
@ -691,17 +691,17 @@ class FragmentHierarchyConflictTestCase(FHDLTestCase):
|
||||||
def test_conflict_memory_error(self):
|
def test_conflict_memory_error(self):
|
||||||
self.setUp_memory()
|
self.setUp_memory()
|
||||||
|
|
||||||
with self.assertRaises(DriverConflict,
|
with self.assertRaisesRegex(DriverConflict,
|
||||||
msg="Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
r"^Memory 'm' is accessed from multiple fragments: top\.<unnamed #0>, "
|
||||||
"top.<unnamed #1>"):
|
r"top\.<unnamed #1>$"):
|
||||||
self.f1._resolve_hierarchy_conflicts(mode="error")
|
self.f1._resolve_hierarchy_conflicts(mode="error")
|
||||||
|
|
||||||
def test_conflict_memory_warning(self):
|
def test_conflict_memory_warning(self):
|
||||||
self.setUp_memory()
|
self.setUp_memory()
|
||||||
|
|
||||||
with self.assertWarns(DriverConflict,
|
with self.assertWarnsRegex(DriverConflict,
|
||||||
msg="Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
(r"^Memory 'm' is accessed from multiple fragments: top.<unnamed #0>, "
|
||||||
"top.<unnamed #1>; hierarchy will be flattened"):
|
r"top.<unnamed #1>; hierarchy will be flattened$")):
|
||||||
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
self.f1._resolve_hierarchy_conflicts(mode="warn")
|
||||||
|
|
||||||
def test_explicit_flatten(self):
|
def test_explicit_flatten(self):
|
||||||
|
@ -783,16 +783,16 @@ class InstanceTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_wrong_construct_arg(self):
|
def test_wrong_construct_arg(self):
|
||||||
s = Signal()
|
s = Signal()
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Instance argument ('', 's1', (sig s)) should be a tuple "
|
(r"^Instance argument \('', 's1', \(sig s\)\) should be a tuple "
|
||||||
"(kind, name, value) where kind is one of \"p\", \"i\", \"o\", or \"io\""):
|
r"\(kind, name, value\) where kind is one of \"p\", \"i\", \"o\", or \"io\"$")):
|
||||||
Instance("foo", ("", "s1", s))
|
Instance("foo", ("", "s1", s))
|
||||||
|
|
||||||
def test_wrong_construct_kwarg(self):
|
def test_wrong_construct_kwarg(self):
|
||||||
s = Signal()
|
s = Signal()
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Instance keyword argument x_s1=(sig s) does not start with one of "
|
(r"^Instance keyword argument x_s1=\(sig s\) does not start with one of "
|
||||||
"\"p_\", \"i_\", \"o_\", or \"io_\""):
|
r"\"p_\", \"i_\", \"o_\", or \"io_\"$")):
|
||||||
Instance("foo", x_s1=s)
|
Instance("foo", x_s1=s)
|
||||||
|
|
||||||
def setUp_cpu(self):
|
def setUp_cpu(self):
|
||||||
|
|
|
@ -20,11 +20,11 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
self.assertEqual(m.depth, 4)
|
self.assertEqual(m.depth, 4)
|
||||||
|
|
||||||
def test_geometry_wrong(self):
|
def test_geometry_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Memory width must be a non-negative integer, not -1"):
|
r"^Memory width must be a non-negative integer, not -1$"):
|
||||||
m = Memory(width=-1, depth=4)
|
m = Memory(width=-1, depth=4)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Memory depth must be a non-negative integer, not -1"):
|
r"^Memory depth must be a non-negative integer, not -1$"):
|
||||||
m = Memory(width=8, depth=-1)
|
m = Memory(width=8, depth=-1)
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
|
@ -32,14 +32,14 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
self.assertEqual(m.init, [0, 1, 2, 3])
|
self.assertEqual(m.init, [0, 1, 2, 3])
|
||||||
|
|
||||||
def test_init_wrong_count(self):
|
def test_init_wrong_count(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Memory initialization value count exceed memory depth (8 > 4)"):
|
r"^Memory initialization value count exceed memory depth \(8 > 4\)$"):
|
||||||
m = Memory(width=8, depth=4, init=range(8))
|
m = Memory(width=8, depth=4, init=range(8))
|
||||||
|
|
||||||
def test_init_wrong_type(self):
|
def test_init_wrong_type(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Memory initialization value at address 1: "
|
(r"^Memory initialization value at address 1: "
|
||||||
"'str' object cannot be interpreted as an integer"):
|
r"'str' object cannot be interpreted as an integer$")):
|
||||||
m = Memory(width=8, depth=4, init=[1, "0"])
|
m = Memory(width=8, depth=4, init=[1, "0"])
|
||||||
|
|
||||||
def test_attrs(self):
|
def test_attrs(self):
|
||||||
|
@ -82,8 +82,8 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_read_port_wrong(self):
|
def test_read_port_wrong(self):
|
||||||
mem = Memory(width=8, depth=4)
|
mem = Memory(width=8, depth=4)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Read port cannot be simultaneously asynchronous and non-transparent"):
|
r"^Read port cannot be simultaneously asynchronous and non-transparent$"):
|
||||||
mem.read_port(domain="comb", transparent=False)
|
mem.read_port(domain="comb", transparent=False)
|
||||||
|
|
||||||
def test_write_port(self):
|
def test_write_port(self):
|
||||||
|
@ -108,14 +108,14 @@ class MemoryTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_write_port_granularity_wrong(self):
|
def test_write_port_granularity_wrong(self):
|
||||||
mem = Memory(width=8, depth=4)
|
mem = Memory(width=8, depth=4)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Write port granularity must be a non-negative integer, not -1"):
|
r"^Write port granularity must be a non-negative integer, not -1$"):
|
||||||
mem.write_port(granularity=-1)
|
mem.write_port(granularity=-1)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Write port granularity must not be greater than memory width (10 > 8)"):
|
r"^Write port granularity must not be greater than memory width \(10 > 8\)$"):
|
||||||
mem.write_port(granularity=10)
|
mem.write_port(granularity=10)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Write port granularity must divide memory width evenly"):
|
r"^Write port granularity must divide memory width evenly$"):
|
||||||
mem.write_port(granularity=3)
|
mem.write_port(granularity=3)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,31 +72,31 @@ class LayoutTestCase(FHDLTestCase):
|
||||||
"('b', Layout([('c', signed(3))]))])")
|
"('b', Layout([('c', signed(3))]))])")
|
||||||
|
|
||||||
def test_wrong_field(self):
|
def test_wrong_field(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Field (1,) has invalid layout: should be either (name, shape) or "
|
(r"^Field \(1,\) has invalid layout: should be either \(name, shape\) or "
|
||||||
"(name, shape, direction)"):
|
r"\(name, shape, direction\)$")):
|
||||||
Layout.cast([(1,)])
|
Layout.cast([(1,)])
|
||||||
|
|
||||||
def test_wrong_name(self):
|
def test_wrong_name(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Field (1, 1) has invalid name: should be a string"):
|
r"^Field \(1, 1\) has invalid name: should be a string$"):
|
||||||
Layout.cast([(1, 1)])
|
Layout.cast([(1, 1)])
|
||||||
|
|
||||||
def test_wrong_name_duplicate(self):
|
def test_wrong_name_duplicate(self):
|
||||||
with self.assertRaises(NameError,
|
with self.assertRaisesRegex(NameError,
|
||||||
msg="Field ('a', 2) has a name that is already present in the layout"):
|
r"^Field \('a', 2\) has a name that is already present in the layout$"):
|
||||||
Layout.cast([("a", 1), ("a", 2)])
|
Layout.cast([("a", 1), ("a", 2)])
|
||||||
|
|
||||||
def test_wrong_direction(self):
|
def test_wrong_direction(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Field ('a', 1, 0) has invalid direction: should be a Direction "
|
(r"^Field \('a', 1, 0\) has invalid direction: should be a Direction "
|
||||||
"instance like DIR_FANIN"):
|
r"instance like DIR_FANIN$")):
|
||||||
Layout.cast([("a", 1, 0)])
|
Layout.cast([("a", 1, 0)])
|
||||||
|
|
||||||
def test_wrong_shape(self):
|
def test_wrong_shape(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Field ('a', 'x') has invalid shape: should be castable to Shape or "
|
(r"^Field \('a', 'x'\) has invalid shape: should be castable to Shape or "
|
||||||
"a list of fields of a nested record"):
|
r"a list of fields of a nested record$")):
|
||||||
Layout.cast([("a", "x")])
|
Layout.cast([("a", "x")])
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,11 +142,11 @@ class RecordTestCase(FHDLTestCase):
|
||||||
("stb", 1),
|
("stb", 1),
|
||||||
("ack", 1),
|
("ack", 1),
|
||||||
])
|
])
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Record 'r' does not have a field 'en'. Did you mean one of: stb, ack?"):
|
r"^Record 'r' does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||||
r["en"]
|
r["en"]
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Record 'r' does not have a field 'en'. Did you mean one of: stb, ack?"):
|
r"^Record 'r' does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||||
r.en
|
r.en
|
||||||
|
|
||||||
def test_wrong_field_unnamed(self):
|
def test_wrong_field_unnamed(self):
|
||||||
|
@ -154,8 +154,8 @@ class RecordTestCase(FHDLTestCase):
|
||||||
("stb", 1),
|
("stb", 1),
|
||||||
("ack", 1),
|
("ack", 1),
|
||||||
])][0]
|
])][0]
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Unnamed record does not have a field 'en'. Did you mean one of: stb, ack?"):
|
r"^Unnamed record does not have a field 'en'\. Did you mean one of: stb, ack\?$"):
|
||||||
r.en
|
r.en
|
||||||
|
|
||||||
def test_construct_with_fields(self):
|
def test_construct_with_fields(self):
|
||||||
|
@ -303,27 +303,27 @@ class ConnectTestCase(FHDLTestCase):
|
||||||
core = Record(self.core_layout)
|
core = Record(self.core_layout)
|
||||||
periph = Record(self.periph_layout)
|
periph = Record(self.periph_layout)
|
||||||
|
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Cannot include field 'foo' because it is not present in record 'core'"):
|
r"^Cannot include field 'foo' because it is not present in record 'core'$"):
|
||||||
core.connect(periph, include={"foo": True})
|
core.connect(periph, include={"foo": True})
|
||||||
|
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Cannot exclude field 'foo' because it is not present in record 'core'"):
|
r"^Cannot exclude field 'foo' because it is not present in record 'core'$"):
|
||||||
core.connect(periph, exclude={"foo": True})
|
core.connect(periph, exclude={"foo": True})
|
||||||
|
|
||||||
def test_wrong_direction(self):
|
def test_wrong_direction(self):
|
||||||
recs = [Record([("x", 1)]) for _ in range(2)]
|
recs = [Record([("x", 1)]) for _ in range(2)]
|
||||||
|
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Cannot connect field 'x' of unnamed record because it does not have "
|
(r"^Cannot connect field 'x' of unnamed record because it does not have "
|
||||||
"a direction"):
|
r"a direction$")):
|
||||||
recs[0].connect(recs[1])
|
recs[0].connect(recs[1])
|
||||||
|
|
||||||
def test_wrong_missing_field(self):
|
def test_wrong_missing_field(self):
|
||||||
core = Record([("addr", 32, DIR_FANOUT)])
|
core = Record([("addr", 32, DIR_FANOUT)])
|
||||||
periph = Record([])
|
periph = Record([])
|
||||||
|
|
||||||
with self.assertRaises(AttributeError,
|
with self.assertRaisesRegex(AttributeError,
|
||||||
msg="Cannot connect field 'addr' of record 'core' to subordinate record 'periph' "
|
(r"^Cannot connect field 'addr' of record 'core' to subordinate record 'periph' "
|
||||||
"because the subordinate record does not have this field"):
|
r"because the subordinate record does not have this field$")):
|
||||||
core.connect(periph)
|
core.connect(periph)
|
||||||
|
|
|
@ -110,13 +110,13 @@ class DomainRenamerTestCase(FHDLTestCase):
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_rename_wrong_to_comb(self):
|
def test_rename_wrong_to_comb(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'sync' may not be renamed to 'comb'"):
|
r"^Domain 'sync' may not be renamed to 'comb'$"):
|
||||||
DomainRenamer("comb")
|
DomainRenamer("comb")
|
||||||
|
|
||||||
def test_rename_wrong_from_comb(self):
|
def test_rename_wrong_from_comb(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'comb' may not be renamed"):
|
r"^Domain 'comb' may not be renamed$"):
|
||||||
DomainRenamer({"comb": "sync"})
|
DomainRenamer({"comb": "sync"})
|
||||||
|
|
||||||
|
|
||||||
|
@ -189,8 +189,8 @@ class DomainLowererTestCase(FHDLTestCase):
|
||||||
self.s.eq(ClockSignal("xxx"))
|
self.s.eq(ClockSignal("xxx"))
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Signal (clk xxx) refers to nonexistent domain 'xxx'"):
|
r"^Signal \(clk xxx\) refers to nonexistent domain 'xxx'$"):
|
||||||
DomainLowerer()(f)
|
DomainLowerer()(f)
|
||||||
|
|
||||||
def test_lower_wrong_reset_less_domain(self):
|
def test_lower_wrong_reset_less_domain(self):
|
||||||
|
@ -201,8 +201,8 @@ class DomainLowererTestCase(FHDLTestCase):
|
||||||
self.s.eq(ResetSignal("sync"))
|
self.s.eq(ResetSignal("sync"))
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assertRaises(DomainError,
|
with self.assertRaisesRegex(DomainError,
|
||||||
msg="Signal (rst sync) refers to reset of reset-less domain 'sync'"):
|
r"^Signal \(rst sync\) refers to reset of reset-less domain 'sync'$"):
|
||||||
DomainLowerer()(f)
|
DomainLowerer()(f)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@ from ..lib.cdc import *
|
||||||
|
|
||||||
class FFSynchronizerTestCase(FHDLTestCase):
|
class FFSynchronizerTestCase(FHDLTestCase):
|
||||||
def test_stages_wrong(self):
|
def test_stages_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||||
FFSynchronizer(Signal(), Signal(), stages=0)
|
FFSynchronizer(Signal(), Signal(), stages=0)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Synchronization stage count may not safely be less than 2"):
|
r"^Synchronization stage count may not safely be less than 2$"):
|
||||||
FFSynchronizer(Signal(), Signal(), stages=1)
|
FFSynchronizer(Signal(), Signal(), stages=1)
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
|
@ -56,16 +56,16 @@ class FFSynchronizerTestCase(FHDLTestCase):
|
||||||
|
|
||||||
class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
||||||
def test_stages_wrong(self):
|
def test_stages_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||||
ResetSynchronizer(Signal(), stages=0)
|
ResetSynchronizer(Signal(), stages=0)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Synchronization stage count may not safely be less than 2"):
|
r"^Synchronization stage count may not safely be less than 2$"):
|
||||||
ResetSynchronizer(Signal(), stages=1)
|
ResetSynchronizer(Signal(), stages=1)
|
||||||
|
|
||||||
def test_edge_wrong(self):
|
def test_edge_wrong(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="AsyncFFSynchronizer async edge must be one of 'pos' or 'neg', not 'xxx'"):
|
r"^AsyncFFSynchronizer async edge must be one of 'pos' or 'neg', not 'xxx'$"):
|
||||||
AsyncFFSynchronizer(Signal(), Signal(), domain="sync", async_edge="xxx")
|
AsyncFFSynchronizer(Signal(), Signal(), domain="sync", async_edge="xxx")
|
||||||
|
|
||||||
def test_pos_edge(self):
|
def test_pos_edge(self):
|
||||||
|
@ -147,11 +147,11 @@ class AsyncFFSynchronizerTestCase(FHDLTestCase):
|
||||||
|
|
||||||
class ResetSynchronizerTestCase(FHDLTestCase):
|
class ResetSynchronizerTestCase(FHDLTestCase):
|
||||||
def test_stages_wrong(self):
|
def test_stages_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||||
ResetSynchronizer(Signal(), stages=0)
|
ResetSynchronizer(Signal(), stages=0)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Synchronization stage count may not safely be less than 2"):
|
r"^Synchronization stage count may not safely be less than 2$"):
|
||||||
ResetSynchronizer(Signal(), stages=1)
|
ResetSynchronizer(Signal(), stages=1)
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
|
@ -196,11 +196,11 @@ class ResetSynchronizerTestCase(FHDLTestCase):
|
||||||
# TODO: test with distinct clocks
|
# TODO: test with distinct clocks
|
||||||
class PulseSynchronizerTestCase(FHDLTestCase):
|
class PulseSynchronizerTestCase(FHDLTestCase):
|
||||||
def test_stages_wrong(self):
|
def test_stages_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Synchronization stage count must be a positive integer, not 0"):
|
r"^Synchronization stage count must be a positive integer, not 0$"):
|
||||||
PulseSynchronizer("w", "r", stages=0)
|
PulseSynchronizer("w", "r", stages=0)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Synchronization stage count may not safely be less than 2"):
|
r"^Synchronization stage count may not safely be less than 2$"):
|
||||||
PulseSynchronizer("w", "r", stages=1)
|
PulseSynchronizer("w", "r", stages=1)
|
||||||
|
|
||||||
def test_smoke(self):
|
def test_smoke(self):
|
||||||
|
|
|
@ -9,11 +9,11 @@ from ..lib.fifo import *
|
||||||
|
|
||||||
class FIFOTestCase(FHDLTestCase):
|
class FIFOTestCase(FHDLTestCase):
|
||||||
def test_depth_wrong(self):
|
def test_depth_wrong(self):
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="FIFO width must be a non-negative integer, not -1"):
|
r"^FIFO width must be a non-negative integer, not -1$"):
|
||||||
FIFOInterface(width=-1, depth=8, fwft=True)
|
FIFOInterface(width=-1, depth=8, fwft=True)
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="FIFO depth must be a non-negative integer, not -1"):
|
r"^FIFO depth must be a non-negative integer, not -1$"):
|
||||||
FIFOInterface(width=8, depth=-1, fwft=True)
|
FIFOInterface(width=8, depth=-1, fwft=True)
|
||||||
|
|
||||||
def test_sync_depth(self):
|
def test_sync_depth(self):
|
||||||
|
@ -37,9 +37,9 @@ class FIFOTestCase(FHDLTestCase):
|
||||||
self.assertEqual(AsyncFIFO(width=8, depth=17).depth, 32)
|
self.assertEqual(AsyncFIFO(width=8, depth=17).depth, 32)
|
||||||
|
|
||||||
def test_async_depth_wrong(self):
|
def test_async_depth_wrong(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="AsyncFIFO only supports depths that are powers of 2; "
|
(r"^AsyncFIFO only supports depths that are powers of 2; "
|
||||||
"requested exact depth 15 is not"):
|
r"requested exact depth 15 is not$")):
|
||||||
AsyncFIFO(width=8, depth=15, exact_depth=True)
|
AsyncFIFO(width=8, depth=15, exact_depth=True)
|
||||||
|
|
||||||
def test_async_buffered_depth(self):
|
def test_async_buffered_depth(self):
|
||||||
|
@ -54,9 +54,9 @@ class FIFOTestCase(FHDLTestCase):
|
||||||
self.assertEqual(AsyncFIFOBuffered(width=8, depth=18).depth, 33)
|
self.assertEqual(AsyncFIFOBuffered(width=8, depth=18).depth, 33)
|
||||||
|
|
||||||
def test_async_buffered_depth_wrong(self):
|
def test_async_buffered_depth_wrong(self):
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="AsyncFIFOBuffered only supports depths that are one higher than powers of 2; "
|
(r"^AsyncFIFOBuffered only supports depths that are one higher than powers of 2; "
|
||||||
"requested exact depth 16 is not"):
|
r"requested exact depth 16 is not$")):
|
||||||
AsyncFIFOBuffered(width=8, depth=16, exact_depth=True)
|
AsyncFIFOBuffered(width=8, depth=16, exact_depth=True)
|
||||||
|
|
||||||
class FIFOModel(Elaboratable, FIFOInterface):
|
class FIFOModel(Elaboratable, FIFOInterface):
|
||||||
|
|
|
@ -541,8 +541,8 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
||||||
|
|
||||||
def test_add_process_wrong(self):
|
def test_add_process_wrong(self):
|
||||||
with self.assertSimulation(Module()) as sim:
|
with self.assertSimulation(Module()) as sim:
|
||||||
with self.assertRaises(TypeError,
|
with self.assertRaisesRegex(TypeError,
|
||||||
msg="Cannot add a process 1 because it is not a generator function"):
|
r"^Cannot add a process 1 because it is not a generator function$"):
|
||||||
sim.add_process(1)
|
sim.add_process(1)
|
||||||
|
|
||||||
def test_add_process_wrong_generator(self):
|
def test_add_process_wrong_generator(self):
|
||||||
|
@ -559,15 +559,15 @@ class SimulatorIntegrationTestCase(FHDLTestCase):
|
||||||
m.d.sync += s.eq(0)
|
m.d.sync += s.eq(0)
|
||||||
with self.assertSimulation(m) as sim:
|
with self.assertSimulation(m) as sim:
|
||||||
sim.add_clock(1)
|
sim.add_clock(1)
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'sync' already has a clock driving it"):
|
r"^Domain 'sync' already has a clock driving it$"):
|
||||||
sim.add_clock(1)
|
sim.add_clock(1)
|
||||||
|
|
||||||
def test_add_clock_wrong_missing(self):
|
def test_add_clock_wrong_missing(self):
|
||||||
m = Module()
|
m = Module()
|
||||||
with self.assertSimulation(m) as sim:
|
with self.assertSimulation(m) as sim:
|
||||||
with self.assertRaises(ValueError,
|
with self.assertRaisesRegex(ValueError,
|
||||||
msg="Domain 'sync' is not present in simulation"):
|
r"^Domain 'sync' is not present in simulation$"):
|
||||||
sim.add_clock(1)
|
sim.add_clock(1)
|
||||||
|
|
||||||
def test_add_clock_if_exists(self):
|
def test_add_clock_if_exists(self):
|
||||||
|
|
|
@ -28,23 +28,6 @@ class FHDLTestCase(unittest.TestCase):
|
||||||
return repr_str.strip()
|
return repr_str.strip()
|
||||||
self.assertEqual(prepare_repr(repr(obj)), prepare_repr(repr_str))
|
self.assertEqual(prepare_repr(repr(obj)), prepare_repr(repr_str))
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def assertRaises(self, exception, msg=None):
|
|
||||||
with super().assertRaises(exception) as cm:
|
|
||||||
yield
|
|
||||||
if msg is not None:
|
|
||||||
# WTF? unittest.assertRaises is completely broken.
|
|
||||||
self.assertEqual(str(cm.exception), msg)
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def assertWarns(self, category, msg=None):
|
|
||||||
with warnings.catch_warnings(record=True) as warns:
|
|
||||||
yield
|
|
||||||
self.assertEqual(len(warns), 1)
|
|
||||||
self.assertEqual(warns[0].category, category)
|
|
||||||
if msg is not None:
|
|
||||||
self.assertEqual(str(warns[0].message), msg)
|
|
||||||
|
|
||||||
def assertFormal(self, spec, mode="bmc", depth=1):
|
def assertFormal(self, spec, mode="bmc", depth=1):
|
||||||
caller, *_ = traceback.extract_stack(limit=2)
|
caller, *_ = traceback.extract_stack(limit=2)
|
||||||
spec_root, _ = os.path.splitext(caller.filename)
|
spec_root, _ = os.path.splitext(caller.filename)
|
||||||
|
|
Loading…
Reference in a new issue