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,14 +459,26 @@ class intbv(object):
# representation
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):
return "intbv(" + repr(self._val) + ")"
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
instance either as signed or unsigned. If the value is classified
@ -503,7 +515,7 @@ class intbv(object):
'''
# 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
msb = self._nrbits-1
@ -520,4 +532,8 @@ class intbv(object):
else: # value is returned just as is
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.access = _access.OUTPUT
self.visit(node.value)
node.obj = node.value.obj
# self.access = _access.INPUT
def getAttr(self, node):
@ -480,6 +481,7 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
raise AssertionError("attribute target: %s" % n)
obj = node.value.obj
if isinstance(obj, _Signal):
print ('analyze', node.value.id)
if node.attr == 'posedge':
node.obj = obj.posedge
elif node.attr == 'negedge':
@ -590,7 +592,12 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
node.obj = delay(0)
### suprize: identity comparison on unbound methods doesn't work in python 2.5??
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:
pass
elif f in builtinObjects:

View File

@ -1347,14 +1347,19 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
else:
a = node.args[argnr]
argnr += 1
to_string = "to_string"
if s.conv is int:
a.vhd = vhd_int()
else:
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):
a.vhd = vhd_boolean()
self.write("write(L, to_string(")
self.write("write(L, %s(" % to_string)
self.visit(a)
self.write("))")
self.write(';')
@ -1987,7 +1992,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
def visit_Attribute(self, node):
self.generic_visit(node)
node.vhd = copy(node.value.vhd)
node.vhd = inferVhdlObj(node.obj)
node.vhdOri = copy(node.vhd)
def visit_Assert(self, node):
@ -2036,6 +2041,7 @@ class _AnnotateTypesVisitor(ast.NodeVisitor, _ConversionMixin):
node.vhd = vhd_nat()
elif f == intbv.signed: # note equality comparison
# this comes from a getattr
# node.vhd = vhd_int()
node.vhd = vhd_signed(fn.value.vhd.size)
elif hasattr(node, 'tree'):
v = _AnnotateTypesVisitor(node.tree)

View File

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

View File

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

View File

@ -68,6 +68,47 @@ def PrintBench():
def testPrint():
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

View File

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

View File

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