Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ ipynb-examples/.ipynb_checkpoints

# VS Code
.vscode

# Python venv
pyvenv.cfg
22 changes: 13 additions & 9 deletions pyrtl/helperfuncs.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,20 +789,29 @@
raise PyrtlError('error, "signed" option with verilog-style string constants not supported')

bases = {'b': 2, 'o': 8, 'd': 10, 'h': 16, 'x': 16}
passed_bitwidth = bitwidth

neg = False
if val.startswith('-'):
neg = True
val = val[1:]

split_string = val.lower().split("'")
if len(split_string) != 2:
raise PyrtlError('error, string not in verilog style format')
try:
bitwidth = int(split_string[0])
verilog_bitwidth = int(split_string[0])
bitwidth = bitwidth or verilog_bitwidth # if bitwidth is None, use verilog_bitwidth
if verilog_bitwidth > bitwidth:
raise PyrtlError(
"bitwidth parameter passed (%d) cannot fit Verilog-style constant with bitwidth %d"
% (bitwidth, verilog_bitwidth)
+ " (if bitwidth=None is used, PyRTL will determine the bitwidth from the "
"Verilog-style constant specification)"
)

sval = split_string[1]
if sval[0] == 's':
raise PyrtlError('error, signed integers are not supported in verilog-style constants')
raise PyrtlError('error, signed integers are not supported in Verilog-style constants')

Check warning on line 814 in pyrtl/helperfuncs.py

View check run for this annotation

Codecov / codecov/patch

pyrtl/helperfuncs.py#L814

Added line #L814 was not covered by tests
base = 10
if sval[0] in bases:
base = bases[sval[0]]
Expand All @@ -811,17 +820,12 @@
num = int(sval, base)
except (IndexError, ValueError):
raise PyrtlError('error, string not in verilog style format')

if neg and num:
if (num >> bitwidth - 1):
raise PyrtlError('error, insufficient bits for negative number')
num = (1 << bitwidth) - num

if passed_bitwidth and passed_bitwidth != bitwidth:
raise PyrtlError('error, bitwidth parameter of constant does not match'
' the bitwidth infered from the verilog style specification'
' (if bitwidth=None is used, pyrtl will determine the bitwidth from the'
' verilog-style constant specification)')

if num >> bitwidth != 0:
raise PyrtlError('specified bitwidth %d for verilog constant insufficient to store value %d'
% (bitwidth, num))
Expand Down
8 changes: 6 additions & 2 deletions pyrtl/wire.py
Original file line number Diff line number Diff line change
Expand Up @@ -852,11 +852,15 @@ def __init__(self, bitwidth: int, name: str = '', reset_value: int = None,
super(Register, self).__init__(bitwidth=bitwidth, name=name, block=block)
self.reg_in = None # wire vector setting self.next
if reset_value is not None:
reset_value, rst_bitwidth = infer_val_and_bitwidth(reset_value)
reset_value, rst_bitwidth = infer_val_and_bitwidth(
reset_value,
bitwidth=bitwidth,
)
if rst_bitwidth > bitwidth:
raise PyrtlError(
'reset_value "%s" cannot fit in the specified %d bits for this register'
% (str(reset_value), bitwidth))
% (str(reset_value), bitwidth)
)
self.reset_value = reset_value

@property
Expand Down
30 changes: 27 additions & 3 deletions tests/test_wire.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,38 @@ def test_reset_value_as_string(self):
self.assertEqual(r.reset_value, 1)

def test_invalid_reset_value_too_large(self):
with self.assertRaisesRegex(pyrtl.PyrtlError, "cannot fit in the specified"):
with self.assertRaises(pyrtl.PyrtlError):
r = pyrtl.Register(4, reset_value=16)

def test_invalid_reset_value_too_large_as_string(self):
with self.assertRaisesRegex(pyrtl.PyrtlError, "cannot fit in the specified"):
with self.assertRaises(pyrtl.PyrtlError):
r = pyrtl.Register(4, reset_value="5'd16")

def test_negative_reset_value(self):
r = pyrtl.Register(4, reset_value=-4)
self.assertEqual(
pyrtl.helperfuncs.val_to_signed_integer(r.reset_value, r.bitwidth),
-4
)

def test_negative_reset_value_as_string(self):
r = pyrtl.Register(4, reset_value="-4'd1")
self.assertEqual(
pyrtl.helperfuncs.val_to_signed_integer(r.reset_value, r.bitwidth),
-1
)

def test_invalid_negative_reset_value_as_string(self):
with self.assertRaises(pyrtl.PyrtlError):
r = pyrtl.Register(2, reset_value="-4'd1")

def test_extending_negative_reset_value_as_string(self):
r = pyrtl.Register(4, reset_value="-3'd3")
self.assertEqual(
pyrtl.helperfuncs.val_to_signed_integer(r.reset_value, r.bitwidth),
-3
)

def test_invalid_reset_value_not_an_integer(self):
with self.assertRaises(pyrtl.PyrtlError):
r = pyrtl.Register(4, reset_value='hello')
Expand Down Expand Up @@ -345,7 +370,6 @@ def test_bad_string(self):
self.assert_bad_const("5'b111111'")
self.assert_bad_const("'")
self.assert_bad_const("'1")
self.assert_bad_const("2'b01", bitwidth=3)
self.assert_bad_const("1'")

def test_bool(self):
Expand Down