1
0
mirror of https://github.com/myhdl/myhdl.git synced 2025-01-24 21:52:56 +08:00

Use to_string to support long vectors; with various implications...

This commit is contained in:
Jan Decaluwe 2016-03-04 17:42:50 +01:00
parent 0d9dc8f45a
commit 86ec7e81c9
8 changed files with 224 additions and 139 deletions

View File

@ -459,65 +459,81 @@ class intbv(object):
# representation # representation
def __str__(self): def __str__(self):
return str(self._val) # represent in hex format, to handle VHDL long vectors
v = int(self._val)
nrbits = self._nrbits
if nrbits:
# represent negative values without minus sign
# I would prefer sign extension with hex format, but to
# align with Verilog $display I don't do that
if v < 0:
v = 2**nrbits + v
w = (nrbits-1) // 4 + 1
return "{:0{w}x}".format(v, w=w)
else:
return "{:x}".format(v)
def __repr__(self): def __repr__(self):
return "intbv(" + repr(self._val) + ")" return "intbv(" + repr(self._val) + ")"
def signed(self): def signed(self):
''' return integer with the signed value of the intbv instance ''' Return new intbv with the values interpreted as signed
The intbv.signed() function will classify the value of the intbv The intbv.signed() function will classify the value of the intbv
instance either as signed or unsigned. If the value is classified instance either as signed or unsigned. If the value is classified
as signed it will be returned unchanged as integer value. If the as signed it will be returned unchanged as integer value. If the
value is considered unsigned, the bits as specified by _nrbits value is considered unsigned, the bits as specified by _nrbits
will be considered as 2's complement number and returned. This will be considered as 2's complement number and returned. This
feature will allow to create slices and have the sliced bits be feature will allow to create slices and have the sliced bits be
considered a 2's complement number. considered a 2's complement number.
The classification is based on the following possible combinations The classification is based on the following possible combinations
of the min and max value. of the min and max value.
----+----+----+----+----+----+----+---- ----+----+----+----+----+----+----+----
-3 -2 -1 0 1 2 3 -3 -2 -1 0 1 2 3
1 min max 1 min max
2 min max 2 min max
3 min max 3 min max
4 min max 4 min max
5 min max 5 min max
6 min max 6 min max
7 min max 7 min max
8 neither min nor max is set 8 neither min nor max is set
9 only max is set 9 only max is set
10 only min is set 10 only min is set
From the above cases, # 1 and 2 are considered unsigned and the From the above cases, # 1 and 2 are considered unsigned and the
signed() function will convert the value to a signed number. signed() function will convert the value to a signed number.
Decision about the sign will be done based on the msb. The msb is Decision about the sign will be done based on the msb. The msb is
based on the _nrbits value. based on the _nrbits value.
So the test will be if min >= 0 and _nrbits > 0. Then the instance So the test will be if min >= 0 and _nrbits > 0. Then the instance
is considered unsigned and the value is returned as 2's complement is considered unsigned and the value is returned as 2's complement
number. number.
''' '''
# value is considered unsigned # value is considered unsigned
if self.min is not None and self.min >= 0 and self._nrbits > 0: if self.min is not None and self.min >= 0 and self._nrbits:
# get 2's complement value of bits # get 2's complement value of bits
msb = self._nrbits-1 msb = self._nrbits-1
sign = ((self._val >> msb) & 0x1) > 0 sign = ((self._val >> msb) & 0x1) > 0
# mask off the bits msb-1:lsb, they are always positive # mask off the bits msb-1:lsb, they are always positive
mask = (1<<msb) - 1 mask = (1<<msb) - 1
retVal = self._val & mask retVal = self._val & mask
# if sign bit is set, subtract the value of the sign bit # if sign bit is set, subtract the value of the sign bit
if sign: if sign:
retVal -= 1<<msb retVal -= 1<<msb
else: # value is returned just as is else: # value is returned just as is
retVal = self._val retVal = self._val
return retVal if self._nrbits:
M = 2**(self._nrbits-1)
return intbv(retVal, min=-M, max=M)
else:
return intbv(retVal)

View File

@ -469,6 +469,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
self.tree.kind = _kind.TASK self.tree.kind = _kind.TASK
# self.access = _access.OUTPUT # self.access = _access.OUTPUT
self.visit(node.value) self.visit(node.value)
node.obj = node.value.obj
# self.access = _access.INPUT # self.access = _access.INPUT
def getAttr(self, node): def getAttr(self, node):
@ -480,6 +481,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
raise AssertionError("attribute target: %s" % n) raise AssertionError("attribute target: %s" % n)
obj = node.value.obj obj = node.value.obj
if isinstance(obj, _Signal): if isinstance(obj, _Signal):
print ('analyze', node.value.id)
if node.attr == 'posedge': if node.attr == 'posedge':
node.obj = obj.posedge node.obj = obj.posedge
elif node.attr == 'negedge': elif node.attr == 'negedge':
@ -590,7 +592,12 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = delay(0) node.obj = delay(0)
### suprize: identity comparison on unbound methods doesn't work in python 2.5?? ### suprize: identity comparison on unbound methods doesn't work in python 2.5??
elif f == intbv.signed: elif f == intbv.signed:
node.obj = int(-1) obj = node.func.value.obj
if len(obj):
M = 2 ** (len(obj)-1)
node.obj = intbv(-1, min=-M, max=M)
else:
node.obj = intbv(-1)
elif f in myhdlObjects: elif f in myhdlObjects:
pass pass
elif f in builtinObjects: elif f in builtinObjects:

View File

@ -1347,14 +1347,19 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else: else:
a = node.args[argnr] a = node.args[argnr]
argnr += 1 argnr += 1
to_string = "to_string"
if s.conv is int: if s.conv is int:
a.vhd = vhd_int() a.vhd = vhd_int()
else: else:
if isinstance(a.vhdOri, vhd_vector): if isinstance(a.vhdOri, vhd_vector):
a.vhd = vhd_int() to_string = "to_hstring"
# to_hstring correctly does sign extension
# however, Verilog doesn not: therefore, interprete
# print values as unsigned...
a.vhd = vhd_unsigned(a.vhd.size)
elif isinstance(a.vhdOri, vhd_std_logic): elif isinstance(a.vhdOri, vhd_std_logic):
a.vhd = vhd_boolean() a.vhd = vhd_boolean()
self.write("write(L, to_string(") self.write("write(L, %s(" % to_string)
self.visit(a) self.visit(a)
self.write("))") self.write("))")
self.write(';') self.write(';')
@ -1987,7 +1992,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Attribute(self, node): def visit_Attribute(self, node):
self.generic_visit(node) self.generic_visit(node)
node.vhd = copy(node.value.vhd) node.vhd = inferVhdlObj(node.obj)
node.vhdOri = copy(node.vhd) node.vhdOri = copy(node.vhd)
def visit_Assert(self, node): def visit_Assert(self, node):
@ -2036,6 +2041,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_nat() node.vhd = vhd_nat()
elif f == intbv.signed: # note equality comparison elif f == intbv.signed: # note equality comparison
# this comes from a getattr # this comes from a getattr
# node.vhd = vhd_int()
node.vhd = vhd_signed(fn.value.vhd.size) node.vhd = vhd_signed(fn.value.vhd.size)
elif hasattr(node, 'tree'): elif hasattr(node, 'tree'):
v = _AnnotateTypesVisitor(node.tree) v = _AnnotateTypesVisitor(node.tree)

View File

@ -1061,7 +1061,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
a = node.args[argnr] a = node.args[argnr]
argnr += 1 argnr += 1
obj = a.obj obj = a.obj
fs = "%0d" if s.conv is int or isinstance(obj, int):
fs = "%0d"
else:
fs = "%h"
self.context =_context.PRINT self.context =_context.PRINT
if isinstance(obj, str): if isinstance(obj, str):
self.write('$write(') self.write('$write(')
@ -1092,6 +1095,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
self.writeline() self.writeline()
self.write("endcase") self.write("endcase")
else: else:
print (type(obj), type(a))
self.write('$write("%s", ' % fs) self.write('$write("%s", ' % fs)
self.visit(a) self.visit(a)
self.write(');') self.write(');')

View File

@ -57,80 +57,80 @@ def PlainIntbv():
# intbv with positive range, pos number, and msb not set, return signed() # intbv with positive range, pos number, and msb not set, return signed()
# Expect the number to be returned # Expect the number to be returned
a1 = intbv(0x3b, min=0, max=0x7c) a1 = intbv(0x3b, min=0, max=0x7c)
b = a1.signed() b1 = a1.signed()
assert b == 0x3b assert b1 == 0x3b
# intbv with positive range, pos number, and msb set, return signed() # intbv with positive range, pos number, and msb set, return signed()
# test various bit patterns to see that the 2's complement # test various bit patterns to see that the 2's complement
# conversion works correct # conversion works correct
# Expect the number to be converted to a negative number # Expect the number to be converted to a negative number
a2 = intbv(7, min=0, max=8) a2 = intbv(7, min=0, max=8)
b = a2.signed() b2 = a2.signed()
assert b == -1 assert b2 == -1
a3 = intbv(6, min=0, max=8) a3 = intbv(6, min=0, max=8)
b = a3.signed() b3 = a3.signed()
assert b == -2 assert b3 == -2
a4 = intbv(5, min=0, max=8) a4 = intbv(5, min=0, max=8)
b = a4.signed() b4 = a4.signed()
assert b == -3 assert b4 == -3
# set bit #3 and increase the range so that the set bit is considered # set bit #3 and increase the range so that the set bit is considered
# the sign bit. Here min = 0 # the sign bit. Here min = 0
# Expect to return -4 # Expect to return -4
a5 = intbv(4, min=0, max=5) a5 = intbv(4, min=0, max=5)
b = a5.signed() b5 = a5.signed()
assert b == -4 assert b5 == -4
a6 = intbv(4, min=0, max=6) a6 = intbv(4, min=0, max=6)
b = a6.signed() b6 = a6.signed()
assert b == -4 assert b6 == -4
a7 = intbv(4, min=0, max=7) a7 = intbv(4, min=0, max=7)
b = a7.signed() b7 = a7.signed()
assert b == -4 assert b7 == -4
a8 = intbv(4, min=0, max=8) a8 = intbv(4, min=0, max=8)
b = a8.signed() b8 = a8.signed()
assert b == -4 assert b8 == -4
# here it is not the sign bit anymore # here it is not the sign bit anymore
# Expect the value to be 4 # Expect the value to be 4
a9 = intbv(4, min=0, max=9) a9 = intbv(4, min=0, max=9)
b = a9.signed() b9 = a9.signed()
assert b == 4 assert b9 == 4
# set bit #3 and increase the range so that the set bit is considered # set bit #3 and increase the range so that the set bit is considered
# the sign bit. Here min > 0 # the sign bit. Here min > 0
# Expect to return -4 # Expect to return -4
a10 = intbv(4, min=1, max=5) a10 = intbv(4, min=1, max=5)
b = a10.signed() b10 = a10.signed()
assert b == -4 assert b10 == -4
a11 = intbv(4, min=2, max=6) a11 = intbv(4, min=2, max=6)
b = a11.signed() b11 = a11.signed()
assert b == -4 assert b11 == -4
a12 = intbv(4, min=3, max=7) a12 = intbv(4, min=3, max=7)
b = a12.signed() b12 = a12.signed()
assert b == -4 assert b12 == -4
a13 = intbv(4, min=4, max=8) a13 = intbv(4, min=4, max=8)
b = a13.signed() b13 = a13.signed()
assert b == -4 assert b13 == -4
# again with min > 0, here it is not the sign bit anymore # again with min > 0, here it is not the sign bit anymore
# Expect the value to be 4 # Expect the value to be 4
a14 = intbv(4, min=2, max=9) a14 = intbv(4, min=2, max=9)
b = a14.signed() b14 = a14.signed()
assert b == 4 assert b14 == 4
# intbv with positive range, value = 0, return signed() # intbv with positive range, value = 0, return signed()
# Expect the number to be returned # Expect the number to be returned
a15 = intbv(0, min=0, max=0x8) a15 = intbv(0, min=0, max=0x8)
b = a15.signed() b15 = a15.signed()
assert b == 0 assert b15 == 0
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -143,55 +143,55 @@ def PlainIntbv():
# msb, but due to the negative range not considered signed # msb, but due to the negative range not considered signed
# Expect to return 4 # Expect to return 4
a20 = intbv(4, min=-1, max=5) a20 = intbv(4, min=-1, max=5)
b = a20.signed() b20 = a20.signed()
assert b == 4 assert b20 == 4
a21 = intbv(4, min=-1, max=6) a21 = intbv(4, min=-1, max=6)
b = a21.signed() b21 = a21.signed()
assert b == 4 assert b21 == 4
a22 = intbv(4, min=-1, max=7) a22 = intbv(4, min=-1, max=7)
b = a22.signed() b22 = a22.signed()
assert b == 4 assert b22 == 4
a23 = intbv(4, min=-1, max=8) a23 = intbv(4, min=-1, max=8)
b = a23.signed() b23 = a23.signed()
assert b == 4 assert b23 == 4
# intbv with negative range, pos number, and msb set, return signed() # intbv with negative range, pos number, and msb set, return signed()
# Expect the number to returned as is # Expect the number to returned as is
a24 = intbv(7, min=-1, max=8) a24 = intbv(7, min=-1, max=8)
b = a24.signed() b24 = a24.signed()
assert b == 7 assert b24 == 7
a25 = intbv(6, min=-1, max=8) a25 = intbv(6, min=-1, max=8)
b = a25.signed() b25 = a25.signed()
assert b == 6 assert b25 == 6
a26 = intbv(5, min=-1, max=8) a26 = intbv(5, min=-1, max=8)
b = a26.signed() b26 = a26.signed()
assert b == 5 assert b26 == 5
# intbv with symmetric (min = -max) range, pos value, msb set # intbv with symmetric (min = -max) range, pos value, msb set
# return signed() # return signed()
# Expect value returned as is # Expect value returned as is
a27 = intbv(4, min=-8, max=8) a27 = intbv(4, min=-8, max=8)
b = a27.signed() b27 = a27.signed()
assert b == 4 assert b27 == 4
# intbv with symmetric (min = -max) range, neg value, # intbv with symmetric (min = -max) range, neg value,
# return signed() # return signed()
# Expect value returned as is # Expect value returned as is
a28 = intbv(-4, min=-8, max=8) a28 = intbv(-4, min=-8, max=8)
b = a28.signed() b28 = a28.signed()
assert b == -4 assert b28 == -4
# intbv with symmetric (min=-max) range, value = 0, # intbv with symmetric (min=-max) range, value = 0,
# return signed() # return signed()
# Expect value returned as is # Expect value returned as is
a29 = intbv(0, min=-8, max=8) a29 = intbv(0, min=-8, max=8)
b = a29.signed() b29 = a29.signed()
assert b == 0 assert b29 == 0
return logic return logic

View File

@ -68,6 +68,47 @@ def PrintBench():
def testPrint(): def testPrint():
assert conversion.verify(PrintBench) == 0 assert conversion.verify(PrintBench) == 0
def PrintLongVectorsBench():
N84 = 84
M84 = 2**N84-1
N85 = 85
M85 = 2**N85-1
N86 = 86
M86 = 2**N86-1
N87 = 87
M87 = 2**N87-1
si1 = Signal(intbv(0)[N87:])
si2 = Signal(intbv(0, min=-M85, max=M86))
@instance
def logic():
i1 = intbv(0)[N85:]
i2 = intbv(0, min=-M86, max=M85)
si1.next = 0
si2.next = 0
yield delay(10)
print("%s %s %s %s" % (i1, i2, si1, si2))
i1[:] = M84
i2[:] = -1
si1.next = M85
si2.next = -1
yield delay(10)
print("%s %s %s %s" % (i1, i2, si1, si2))
i1[:] = 596854
i2[:] = -4954502
si1.next = 232434
si2.next = -3434355
yield delay(10)
print("%s %s %s %s" % (i1, i2, si1, si2))
return logic
def testPrintLongVectors():
assert conversion.verify(PrintLongVectorsBench) == 0
def testPrint():
assert conversion.verify(PrintBench) == 0
# format string errors and unsupported features # format string errors and unsupported features

View File

@ -39,11 +39,14 @@ def binaryOps(
Bitand.next = left & right Bitand.next = left & right
Bitor.next = left | right Bitor.next = left | right
Bitxor.next = left ^ right Bitxor.next = left ^ right
FloorDiv.next = 0
if right != 0: if right != 0:
FloorDiv.next = left // right FloorDiv.next = left // right
## if left < 256 and right < 40: ## if left < 256 and right < 40:
LeftShift.next = 0
if left < 256 and right < 26: # fails in ghdl for > 26 if left < 256 and right < 26: # fails in ghdl for > 26
LeftShift.next = left << right LeftShift.next = left << right
Modulo.next = 0
if right != 0: if right != 0:
Modulo.next = left % right Modulo.next = left % right
Mul.next = left * right Mul.next = left * right
@ -52,6 +55,7 @@ def binaryOps(
# Pow.next = left ** right # Pow.next = left ** right
## Pow.next = 0 ## Pow.next = 0
RightShift.next = left >> right RightShift.next = left >> right
Sub.next = 0
if left >= right: if left >= right:
Sub.next = left - right Sub.next = left - right
Sum.next = left + right Sum.next = left + right
@ -358,10 +362,12 @@ def augmOps( Bitand,
var[:] = left var[:] = left
var ^= left var ^= left
Bitxor.next = var Bitxor.next = var
FloorDiv.next = 0
if right != 0: if right != 0:
var[:] = left var[:] = left
var //= right var //= right
FloorDiv.next = var FloorDiv.next = var
Sub.next = 0
if left >= right: if left >= right:
var[:] = left var[:] = left
var -= right var -= right
@ -369,10 +375,12 @@ def augmOps( Bitand,
var[:] = left var[:] = left
var += right var += right
Sum.next = var Sum.next = var
LeftShift.next = 0
if left < 256 and right < 26: if left < 256 and right < 26:
var2[:] = left var2[:] = left
var2 <<= right var2 <<= right
LeftShift.next = var2 LeftShift.next = var2
Modulo.next = 0
if right != 0: if right != 0:
var[:] = left var[:] = left
var %= right var %= right

View File

@ -42,6 +42,7 @@ def binaryOps(
## if right != 0: ## if right != 0:
## FloorDiv.next = left // right ## FloorDiv.next = left // right
# Keep left shifts smaller than 2** 31 for VHDL's to_integer # Keep left shifts smaller than 2** 31 for VHDL's to_integer
LeftShift.next = 0
if left < 256 and right < 22 and right >= 0: if left < 256 and right < 22 and right >= 0:
LeftShift.next = left << right LeftShift.next = left << right
## if right != 0: ## if right != 0:
@ -308,6 +309,7 @@ def augmOps(
## var[:] = left ## var[:] = left
## var //= right ## var //= right
## FloorDiv.next = var ## FloorDiv.next = var
LeftShift.next = 0
if left < 256 and right < 22 and right >= 0: if left < 256 and right < 22 and right >= 0:
var2[:] = left var2[:] = left
var2 <<= right var2 <<= right
@ -321,6 +323,7 @@ def augmOps(
Mul.next = var Mul.next = var
var[:] = left var[:] = left
RightShift.next = 0
if right >= 0: if right >= 0:
var >>= right var >>= right
RightShift.next = var RightShift.next = var