Skip to content

Commit e5ad017

Browse files
committed
extending improvements to twos complement handling to Const class
1 parent f15f5d6 commit e5ad017

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

pyrtl/helperfuncs.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ def _convert_int(val, bitwidth=None, signed=False):
514514

515515
def _convert_verilog_str(val, bitwidth=None, signed=False):
516516
if signed:
517-
raise PyrtlError('error, signed verilog-style string constants not supported currently')
517+
raise PyrtlError('error, "signed" option with verilog-style string constants not supported')
518518

519519
bases = {'b': 2, 'o': 8, 'd': 10, 'h': 16, 'x': 16}
520520
passed_bitwidth = bitwidth
@@ -550,6 +550,10 @@ def _convert_verilog_str(val, bitwidth=None, signed=False):
550550
' (if bitwidth=None is used, pyrtl will determine the bitwidth from the'
551551
' verilog-style constant specification)')
552552

553+
if num >> bitwidth != 0:
554+
raise PyrtlError('specified bitwidth %d for verilog constant insufficient to store value %d'
555+
% (bitwidth, num))
556+
553557
return ValueBitwidthTuple(num, bitwidth)
554558

555559

pyrtl/wire.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -578,26 +578,37 @@ class Const(WireVector):
578578

579579
_code = 'C'
580580

581-
def __init__(self, val, bitwidth=None, block=None):
581+
def __init__(self, val, bitwidth=None, signed=False, block=None):
582582
""" Construct a constant implementation at initialization
583583
584-
:param int or str val: The value for the const wirevector
584+
:param int, bool, or str val: The value for the const wirevector
585+
:param int: the desired bitwidth of the resulting const
586+
:param signed: specify if bits should be used for twos complement
585587
:return: a wirevector object representing a const wire
586588
587589
Descriptions for all parameters not listed above can be found at
588590
py:method:: WireVector.__init__()
591+
592+
For details of how constants are converted fron int, bool, and
593+
strings (for verilog constants), see documentation for the
594+
helper function infer_val_and_bitwidth. Please note that a
595+
a constant generated with signed=True is still just a raw bitvector
596+
and all arthimetic on it is unsigned by default. The signed=True
597+
argument is only used for proper inference of WireVector size and certain
598+
bitwidth sanity checks assuming a two's complement representation of
599+
the constants.
589600
"""
590601
self._validate_bitwidth(bitwidth)
591602
from .helperfuncs import infer_val_and_bitwidth
592-
num, bitwidth = infer_val_and_bitwidth(val, bitwidth)
603+
num, bitwidth = infer_val_and_bitwidth(val, bitwidth, signed)
593604

594605
if num < 0:
595606
raise PyrtlInternalError(
596607
'Const somehow evaluating to negative integer after checks')
597608
if (num >> bitwidth) != 0:
598-
raise PyrtlError(
599-
'error constant "%s" cannot fit in the specified %d bits'
600-
% (str(num), bitwidth))
609+
raise PyrtlInternalError(
610+
'constant %d returned by infer_val_and_bitwidth somehow not fitting in %d bits'
611+
% (num, bitwidth))
601612

602613
name = _constIndexer.make_valid_string() + '_' + str(val)
603614

tests/test_wire.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,23 @@ def test_integers(self):
235235
self.check_const(1, 1, 1)
236236
self.check_const(5, 5, 3)
237237
self.check_const(1, 1, 5, bitwidth=5)
238+
self.check_const(0, 0b0, 1)
239+
self.check_const(0, 0b0, 1, signed=True)
240+
self.check_const(1, 0b01, 2, signed=True)
241+
self.check_const(2, 0b010, 3, signed=True)
242+
self.check_const(3, 0b011, 3, signed=True)
243+
self.check_const(4, 0b0100, 4, signed=True)
244+
self.check_const(5, 0b0101, 4, signed=True)
238245

239246
def test_neg_integers(self):
240247
self.check_const(-1, 0b11111, 5, bitwidth=5)
241248
self.check_const(-2, 0b110, 3, bitwidth=3)
242249
self.check_const(-5, 0b1011, 4, bitwidth=4)
250+
self.check_const(-1, 0b1, 1, signed=True)
251+
self.check_const(-2, 0b10, 2, signed=True)
252+
self.check_const(-3, 0b101, 3, signed=True)
253+
self.check_const(-4, 0b100, 3, signed=True)
254+
self.check_const(-5, 0b1011, 4, signed=True)
243255

244256
def test_too_big(self):
245257
self.assert_bad_const(5, 2)

0 commit comments

Comments
 (0)