Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 083016d747f2
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 360bc9b5b462
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Apr 21, 2019

  1. hdl.ast: accept Signals with identical min/max bounds.

    And produce a 0-bit signal.
    
    Fixes #58.
    whitequark committed Apr 21, 2019
    Copy the full SHA
    33f9bd2 View commit details
  2. hdl.ast: improve tests for exceptional conditions.

    whitequark committed Apr 21, 2019
    Copy the full SHA
    360bc9b View commit details
Showing with 40 additions and 19 deletions.
  1. +8 −4 nmigen/hdl/ast.py
  2. +32 −15 nmigen/test/test_hdl_ast.py
12 changes: 8 additions & 4 deletions nmigen/hdl/ast.py
Original file line number Diff line number Diff line change
@@ -593,11 +593,15 @@ def __init__(self, shape=None, name=None, reset=0, reset_less=False, min=None, m
if max is None:
max = 2
max -= 1 # make both bounds inclusive
if not min < max:
raise ValueError("Lower bound {} should be less than higher bound {}"
.format(min, max))
if min > max:
raise ValueError("Lower bound {} should be less or equal to higher bound {}"
.format(min, max + 1))
self.signed = min < 0 or max < 0
self.nbits = builtins.max(bits_for(min, self.signed), bits_for(max, self.signed))
if min == max:
self.nbits = 0
else:
self.nbits = builtins.max(bits_for(min, self.signed),
bits_for(max, self.signed))

else:
if not (min is None and max is None):
47 changes: 32 additions & 15 deletions nmigen/test/test_hdl_ast.py
Original file line number Diff line number Diff line change
@@ -8,11 +8,13 @@ def test_wrap(self):
self.assertIsInstance(Value.wrap(True), Const)
c = Const(0)
self.assertIs(Value.wrap(c), c)
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Object ''str'' is not an nMigen value"):
Value.wrap("str")

def test_bool(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Attempted to convert nMigen value to boolean"):
if Const(0):
pass

@@ -28,7 +30,8 @@ def test_getitem_int(self):
self.assertIsInstance(s2, Slice)
self.assertEqual(s2.start, 3)
self.assertEqual(s2.end, 4)
with self.assertRaises(IndexError):
with self.assertRaises(IndexError,
msg="Cannot index 5 bits into 4-bit value"):
Const(10)[5]

def test_getitem_slice(self):
@@ -53,7 +56,8 @@ def test_getitem_slice(self):
self.assertEqual(s3.parts[2].end, 5)

def test_getitem_wrong(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Cannot index value with 'str'"):
Const(31)["str"]


@@ -69,7 +73,8 @@ def test_shape(self):
self.assertEqual(Const(0, (0, False)).shape(), (0, False))

def test_shape_bad(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Width must be a non-negative integer, not '-1'"):
Const(1, -1)

def test_normalization(self):
@@ -263,18 +268,23 @@ def test_start_end_negative(self):
self.assertEqual((s1.start, s1.end), (4, 7))

def test_start_end_wrong(self):
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Slice start must be an integer, not ''x''"):
Slice(0, "x", 1)
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Slice end must be an integer, not ''x''"):
Slice(0, 1, "x")

def test_start_end_out_of_range(self):
c = Const(0, 8)
with self.assertRaises(IndexError):
with self.assertRaises(IndexError,
msg="Cannot start slice 10 bits into 8-bit value"):
Slice(c, 10, 12)
with self.assertRaises(IndexError):
with self.assertRaises(IndexError,
msg="Cannot end slice 12 bits into 8-bit value"):
Slice(c, 0, 12)
with self.assertRaises(IndexError):
with self.assertRaises(IndexError,
msg="Slice start 4 must be less than slice end 2"):
Slice(c, 4, 2)

def test_repr(self):
@@ -414,13 +424,18 @@ def test_shape(self):
self.assertEqual(s8.shape(), (6, True))
s9 = Signal(0)
self.assertEqual(s9.shape(), (0, False))
s10 = Signal(max=1)
self.assertEqual(s10.shape(), (0, False))

def test_shape_bad(self):
with self.assertRaises(ValueError):
with self.assertRaises(ValueError,
msg="Lower bound 10 should be less or equal to higher bound 4"):
Signal(min=10, max=4)
with self.assertRaises(ValueError):
with self.assertRaises(ValueError,
msg="Only one of bits/signedness or bounds may be specified"):
Signal(2, min=10)
with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Width must be a non-negative integer, not '-10'"):
Signal(-10)

def test_name(self):
@@ -475,7 +490,8 @@ def test_domain(self):
s2 = ClockSignal("pix")
self.assertEqual(s2.domain, "pix")

with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Clock domain name must be a string, not '1'"):
ClockSignal(1)

def test_shape(self):
@@ -493,7 +509,8 @@ def test_domain(self):
s2 = ResetSignal("pix")
self.assertEqual(s2.domain, "pix")

with self.assertRaises(TypeError):
with self.assertRaises(TypeError,
msg="Clock domain name must be a string, not '1'"):
ResetSignal(1)

def test_shape(self):