mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +08:00
fine-grained signed arithmetic
This commit is contained in:
parent
26a43394c4
commit
1c3a13c946
10
MANIFEST.in
10
MANIFEST.in
@ -8,10 +8,10 @@ global-include makefile*
|
||||
global-include *.v
|
||||
prune dist
|
||||
prune doc
|
||||
graft doc/html/manual
|
||||
graft doc/html/icons
|
||||
graft doc/html/whatsnew*
|
||||
include doc/paper-a4/*.pdf
|
||||
include doc/paper-letter/*.pdf
|
||||
#graft doc/html/manual
|
||||
#graft doc/html/icons
|
||||
#graft doc/html/whatsnew*
|
||||
#include doc/paper-a4/*.pdf
|
||||
#include doc/paper-letter/*.pdf
|
||||
prune myhdl/experiments
|
||||
exclude myhdl/test/toVerilog/*.v
|
||||
|
@ -71,7 +71,7 @@ _error.ListElementNotUnique = "List contains Signals that are not unique to it"
|
||||
|
||||
_access = enum("INPUT", "OUTPUT", "INOUT", "UNKNOWN")
|
||||
_kind = enum("NORMAL", "DECLARATION", "ALWAYS", "INITIAL", "ALWAYS_COMB", "SIMPLE_ALWAYS_COMB", "ALWAYS_DECO", "TASK", "REG")
|
||||
_context = enum("BOOLEAN", "YIELD", "PRINT" ,"EXPR", "UNKNOWN")
|
||||
_context = enum("BOOLEAN", "YIELD", "PRINT" ,"SIGNED", "UNKNOWN")
|
||||
|
||||
|
||||
class _ToVerilogMixin(object):
|
||||
|
@ -48,9 +48,6 @@ from myhdl._extractHierarchy import _isMem, _CustomVerilog
|
||||
myhdlObjects = myhdl.__dict__.values()
|
||||
builtinObjects = __builtin__.__dict__.values()
|
||||
|
||||
_signed = False
|
||||
def _isSigned():
|
||||
return _signed
|
||||
|
||||
def _makeName(n, prefixes):
|
||||
if len(prefixes) > 1:
|
||||
@ -64,7 +61,6 @@ def _makeName(n, prefixes):
|
||||
return name
|
||||
|
||||
def _analyzeSigs(hierarchy):
|
||||
global _signed
|
||||
curlevel = 0
|
||||
siglist = []
|
||||
memlist = []
|
||||
@ -74,24 +70,15 @@ def _analyzeSigs(hierarchy):
|
||||
delta = curlevel - level
|
||||
curlevel = level
|
||||
assert(delta >= -1)
|
||||
#print
|
||||
#print curlevel
|
||||
#print delta
|
||||
#print prefixes
|
||||
if delta == -1:
|
||||
prefixes.append(name)
|
||||
else:
|
||||
prefixes = prefixes[:curlevel-1]
|
||||
prefixes.append(name)
|
||||
assert prefixes[-1] == name
|
||||
#print prefixes
|
||||
# signals
|
||||
#print sigdict
|
||||
for n, s in sigdict.items():
|
||||
if s._name is not None:
|
||||
continue
|
||||
if s._min is not None and s._min < 0:
|
||||
_signed = True
|
||||
s._name = _makeName(n, prefixes)
|
||||
if not s._nrbits:
|
||||
raise ToVerilogError(_error.UndefinedBitWidth, s._name)
|
||||
@ -120,8 +107,6 @@ def _analyzeSigs(hierarchy):
|
||||
raise ToVerilogError(_error.InconsistentType, s._name)
|
||||
if s._nrbits != m.elObj._nrbits:
|
||||
raise ToVerilogError(_error.InconsistentBitWidth, s._name)
|
||||
if s._min is not None and s._min < 0:
|
||||
_signed = True
|
||||
|
||||
return siglist, memlist
|
||||
|
||||
@ -328,6 +313,11 @@ class _Rom(object):
|
||||
def __init__(self, rom):
|
||||
self.rom = rom
|
||||
|
||||
def _isNegative(obj):
|
||||
if hasattr(obj, '_min') and (obj._min is not None) and (obj._min < 0):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
|
||||
@ -350,18 +340,22 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
self.visit(node.left)
|
||||
self.visit(node.right)
|
||||
node.obj = int()
|
||||
node.signed = node.left.signed or node.right.signed
|
||||
visitAdd = binaryOp
|
||||
visitFloorDiv = binaryOp
|
||||
visitLeftShift = binaryOp
|
||||
visitMul = binaryOp
|
||||
visitPow = binaryOp
|
||||
visitPower = binaryOp
|
||||
visitMod = binaryOp
|
||||
visitRightShift = binaryOp
|
||||
visitSub = binaryOp
|
||||
|
||||
def multiBitOp(self, node, *args):
|
||||
node.signed = False
|
||||
for n in node.nodes:
|
||||
self.visit(n)
|
||||
if n.signed:
|
||||
node.signed = True
|
||||
node.obj = None
|
||||
for n in node.nodes:
|
||||
if node.obj is None:
|
||||
@ -387,15 +381,19 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
def visitInvert(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
node.obj = node.expr.obj
|
||||
node.signed = node.expr.signed
|
||||
def visitNot(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
node.obj = bool()
|
||||
node.signed = node.expr.signed
|
||||
def visitUnaryAdd(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
node.obj = int()
|
||||
node.signed = node.expr.signed
|
||||
def visitUnarySub(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
node.obj = int()
|
||||
node.signed = node.expr.signed
|
||||
|
||||
def visitAssAttr(self, node, access=_access.OUTPUT, *args):
|
||||
if node.attrname != 'next':
|
||||
@ -404,7 +402,6 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
self.visit(node.expr, _access.OUTPUT)
|
||||
|
||||
def visitAssign(self, node, access=_access.OUTPUT, *args):
|
||||
global _signed
|
||||
target, expr = node.nodes[0], node.expr
|
||||
self.visit(target, _access.OUTPUT)
|
||||
if isinstance(target, astNode.AssName):
|
||||
@ -457,6 +454,7 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
argsAreInputs = True
|
||||
f = self.getObj(node.node)
|
||||
node.obj = None
|
||||
node.signed = False
|
||||
if type(f) is type and issubclass(f, intbv):
|
||||
node.obj = self.getVal(node)
|
||||
elif f is len:
|
||||
@ -517,7 +515,11 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
|
||||
def visitCompare(self, node, *args):
|
||||
node.obj = bool()
|
||||
self.visitChildNodes(node)
|
||||
node.signed = False
|
||||
for n in node.getChildNodes():
|
||||
self.visit(n, *args)
|
||||
if n.signed:
|
||||
node.signed = True
|
||||
op, arg = node.ops[0]
|
||||
if op == '==':
|
||||
if isinstance(node.expr, astNode.Name) and \
|
||||
@ -525,6 +527,7 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
node.case = (node.expr.name, arg.obj)
|
||||
|
||||
def visitConst(self, node, *args):
|
||||
node.signed = False
|
||||
if isinstance(node.value, int):
|
||||
node.obj = node.value
|
||||
else:
|
||||
@ -557,6 +560,7 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
assert isinstance(node.expr, astNode.Name)
|
||||
assert node.expr.name in self.ast.symdict
|
||||
node.obj = None
|
||||
node.signed = False
|
||||
obj = self.ast.symdict[node.expr.name]
|
||||
if isinstance(obj, Signal):
|
||||
if node.attrname in ('posedge', 'negedge'):
|
||||
@ -645,11 +649,13 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
node.obj = __builtin__.__dict__[n]
|
||||
else:
|
||||
pass
|
||||
node.signed = _isNegative(node.obj)
|
||||
|
||||
def visitReturn(self, node, *args):
|
||||
self.raiseError(node, _error.NotSupported, "return statement")
|
||||
|
||||
def visitSlice(self, node, access=_access.INPUT, kind=_kind.NORMAL, *args):
|
||||
node.signed = False
|
||||
self.visit(node.expr, access)
|
||||
node.obj = self.getObj(node.expr)
|
||||
if node.lower:
|
||||
@ -668,6 +674,7 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
|
||||
|
||||
def visitSubscript(self, node, access=_access.INPUT, *args):
|
||||
node.signed = False
|
||||
self.visit(node.expr, access)
|
||||
assert len(node.subs) == 1
|
||||
self.visit(node.subs[0], _access.INPUT)
|
||||
|
@ -46,7 +46,7 @@ from myhdl._always import _Always
|
||||
from myhdl._toVerilog import _error, _access, _kind,_context, \
|
||||
_ToVerilogMixin, _Label
|
||||
from myhdl._toVerilog._analyze import _analyzeSigs, _analyzeGens, _analyzeTopFunc, \
|
||||
_Ram, _Rom, _isSigned
|
||||
_Ram, _Rom
|
||||
|
||||
_converting = 0
|
||||
_profileFunc = None
|
||||
@ -234,16 +234,12 @@ def _getRangeString(s):
|
||||
return ''
|
||||
elif s._nrbits is not None:
|
||||
nrbits = s._nrbits
|
||||
if _isSigned():
|
||||
# add a sign bit to positive numbers
|
||||
if s._type is intbv and s._min >=0:
|
||||
nrbits += 1
|
||||
return "[%s:0] " % (nrbits-1)
|
||||
else:
|
||||
raise AssertionError
|
||||
|
||||
def _getSignString(s):
|
||||
if _isSigned() and s._type is intbv:
|
||||
if s._min is not None and s._min < 0:
|
||||
return "signed "
|
||||
else:
|
||||
return ''
|
||||
@ -301,8 +297,9 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
self.write("reg [%s-1:0] %s [0:%s-1]" % (obj.elObj._nrbits, name, obj.depth))
|
||||
elif hasattr(obj, '_nrbits'):
|
||||
s = ""
|
||||
if isinstance(obj, intbv) and obj._min < 0:
|
||||
s = "signed "
|
||||
if isinstance(obj, (intbv, Signal)):
|
||||
if obj._min is not None and obj._min < 0:
|
||||
s = "signed "
|
||||
self.write("%s%s[%s-1:0] %s" % (dir, s, obj._nrbits, name))
|
||||
else:
|
||||
raise AssertionError("var %s has unexpected type %s" % (name, type(obj)))
|
||||
@ -331,10 +328,13 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
self.ind = self.ind[:-4]
|
||||
|
||||
def binaryOp(self, node, op=None):
|
||||
context = None
|
||||
if node.signed:
|
||||
context = _context.SIGNED
|
||||
self.write("(")
|
||||
self.visit(node.left, _context.EXPR)
|
||||
self.visit(node.left, context)
|
||||
self.write(" %s " % op)
|
||||
self.visit(node.right, _context.EXPR)
|
||||
self.visit(node.right, context)
|
||||
self.write(")")
|
||||
def visitAdd(self, node, *args):
|
||||
self.binaryOp(node, '+')
|
||||
@ -374,7 +374,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
self.visit(node.nodes[0])
|
||||
for n in node.nodes[1:]:
|
||||
self.write(" %s " % op)
|
||||
self.visit(n, _context.EXPR)
|
||||
self.visit(n)
|
||||
self.write(")")
|
||||
def visitAnd(self, node, *args):
|
||||
self.multiOp(node, '&&')
|
||||
@ -387,19 +387,19 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
def visitOr(self, node, *args):
|
||||
self.multiOp(node, '||')
|
||||
|
||||
def unaryOp(self, node, op):
|
||||
def unaryOp(self, node, op, context):
|
||||
self.checkOpWithNegIntbv(node.expr, op)
|
||||
self.write("(%s" % op)
|
||||
self.visit(node.expr, _context.EXPR)
|
||||
self.visit(node.expr, context)
|
||||
self.write(")")
|
||||
def visitInvert(self, node, *args):
|
||||
self.unaryOp(node, '~')
|
||||
def visitNot(self, node, *args):
|
||||
self.unaryOp(node, '!')
|
||||
def visitUnaryAdd(self, node, *args):
|
||||
self.unaryOp(node, '+')
|
||||
def visitUnarySub(self, node, *args):
|
||||
self.unaryOp(node, '-')
|
||||
def visitInvert(self, node, context=None, *args):
|
||||
self.unaryOp(node, '~', context)
|
||||
def visitNot(self, node, context=None, *args):
|
||||
self.unaryOp(node, '!', context)
|
||||
def visitUnaryAdd(self, node, context=None, *args):
|
||||
self.unaryOp(node, '+', context)
|
||||
def visitUnarySub(self, node, context=None, *args):
|
||||
self.unaryOp(node, '-', context)
|
||||
|
||||
def visitAssAttr(self, node, *args):
|
||||
assert node.attrname == 'next'
|
||||
@ -496,6 +496,9 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
return
|
||||
elif f in (int, long):
|
||||
opening, closing = '', ''
|
||||
elif f is intbv:
|
||||
self.visit(node.args[0])
|
||||
return
|
||||
elif type(f) is ClassType and issubclass(f, Exception):
|
||||
self.write(f.__name__)
|
||||
elif f in (posedge, negedge):
|
||||
@ -523,11 +526,14 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
compiler.walk(node.ast, v)
|
||||
|
||||
def visitCompare(self, node, *args):
|
||||
context = None
|
||||
if node.signed:
|
||||
context = _context.SIGNED
|
||||
self.write("(")
|
||||
self.visit(node.expr)
|
||||
self.visit(node.expr, context)
|
||||
op, code = node.ops[0]
|
||||
self.write(" %s " % op)
|
||||
self.visit(code)
|
||||
self.visit(code, context)
|
||||
self.write(")")
|
||||
|
||||
def visitConst(self, node, context=None, *args):
|
||||
@ -697,54 +703,50 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
def visitModule(self, node, *args):
|
||||
for stmt in node.node.nodes:
|
||||
self.visit(stmt)
|
||||
|
||||
def writeName(self, name, context, isBool):
|
||||
addSignBit = isBool and _isSigned() and context == _context.EXPR
|
||||
if addSignBit:
|
||||
self.write("$signed({1'b0, ")
|
||||
self.write(name)
|
||||
if addSignBit:
|
||||
self.write("})")
|
||||
|
||||
def visitName(self, node, context=None, *args):
|
||||
addSignBit = False
|
||||
isMixedExpr = (not node.signed) and (context == _context.SIGNED)
|
||||
n = node.name
|
||||
if n == 'False':
|
||||
self.write("0")
|
||||
s = "0"
|
||||
elif n == 'True':
|
||||
self.write("1")
|
||||
s = "1"
|
||||
elif n in self.ast.vardict:
|
||||
obj = self.ast.vardict[n]
|
||||
isBool = isinstance(obj, bool)
|
||||
self.writeName(n, context, isBool)
|
||||
addSignBit = isMixedExpr
|
||||
s = n
|
||||
elif n in self.ast.argnames:
|
||||
assert n in self.ast.symdict
|
||||
obj = self.ast.symdict[n]
|
||||
isBool = isinstance(obj, bool) or (isinstance(obj, Signal) and obj._type is bool)
|
||||
self.writeName(n, context, isBool)
|
||||
addSignBit = isMixedExpr
|
||||
s = n
|
||||
elif n in self.ast.symdict:
|
||||
obj = self.ast.symdict[n]
|
||||
if isinstance(obj, bool):
|
||||
self.write("%s" % int(obj))
|
||||
s = "%s" % int(obj)
|
||||
elif isinstance(obj, int):
|
||||
self.write(str(obj))
|
||||
s = str(obj)
|
||||
elif isinstance(obj, Signal):
|
||||
isBool = obj._type is bool
|
||||
assert obj._name
|
||||
self.writeName(obj._name, context, isBool)
|
||||
addSignBit = isMixedExpr
|
||||
s = str(obj)
|
||||
elif _isMem(obj):
|
||||
m = _getMemInfo(obj)
|
||||
assert m.name
|
||||
if not m.decl:
|
||||
self.raiseError(node, _error.ListElementNotUnique, m.name)
|
||||
self.write(m.name)
|
||||
s = m.name
|
||||
elif str(type(obj)) == "<class 'myhdl._enum.EnumItem'>":
|
||||
self.write(obj._toVerilog())
|
||||
s = obj._toVerilog()
|
||||
elif type(obj) is ClassType and issubclass(obj, Exception):
|
||||
self.write(n)
|
||||
s = n
|
||||
else:
|
||||
self.raiseError(node, _error.UnsupportedType, "%s, %s" % (n, type(obj)))
|
||||
else:
|
||||
raise AssertionError("name ref: %s" % n)
|
||||
if addSignBit:
|
||||
self.write("$signed({1'b0, ")
|
||||
self.write(s)
|
||||
if addSignBit:
|
||||
self.write("})")
|
||||
|
||||
def visitPass(self, node, *args):
|
||||
self.write("// pass")
|
||||
@ -774,14 +776,15 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
def visitReturn(self, node, *args):
|
||||
self.write("disable %s;" % self.returnLabel)
|
||||
|
||||
def visitSlice(self, node, *args):
|
||||
def visitSlice(self, node, context=None, *args):
|
||||
if isinstance(node.expr, astNode.CallFunc) and \
|
||||
node.expr.node.obj is intbv:
|
||||
c = self.getVal(node)
|
||||
self.write("%s'h" % c._nrbits)
|
||||
self.write("%x" % c._val)
|
||||
return
|
||||
if node.flags == 'OP_APPLY' and _isSigned():
|
||||
addSignBit = (node.flags == 'OP_APPLY') and (context == _context.SIGNED)
|
||||
if addSignBit:
|
||||
self.write("$signed({1'b0, ")
|
||||
self.visit(node.expr)
|
||||
# special shortcut case for [:] slice
|
||||
@ -798,7 +801,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
else:
|
||||
self.visit(node.upper)
|
||||
self.write("]")
|
||||
if node.flags == 'OP_APPLY' and _isSigned():
|
||||
if addSignBit:
|
||||
self.write("})")
|
||||
|
||||
def visitStmt(self, node, *args):
|
||||
@ -809,15 +812,16 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
if isinstance(stmt, astNode.CallFunc) and hasattr(stmt, 'ast'):
|
||||
self.write(';')
|
||||
|
||||
def visitSubscript(self, node, *args):
|
||||
if node.flags == 'OP_APPLY' and _isSigned():
|
||||
def visitSubscript(self, node, context=None, *args):
|
||||
addSignBit = (node.flags == 'OP_APPLY') and (context == _context.SIGNED)
|
||||
if addSignBit:
|
||||
self.write("$signed({1'b0, ")
|
||||
self.visit(node.expr)
|
||||
self.write("[")
|
||||
assert len(node.subs) == 1
|
||||
self.visit(node.subs[0])
|
||||
self.write("]")
|
||||
if node.flags == 'OP_APPLY' and _isSigned():
|
||||
if addSignBit:
|
||||
self.write("})")
|
||||
|
||||
def visitTuple(self, node, context=None, *args):
|
||||
|
@ -54,6 +54,28 @@ def dec(count, enable, clock, reset, n):
|
||||
count.next = count - 1
|
||||
return decProcess()
|
||||
|
||||
|
||||
def decFunc(count, enable, clock, reset, n):
|
||||
|
||||
def decFuncFunc(cnt):
|
||||
count_next = intbv(0, min=-n, max=n)
|
||||
if count == -n:
|
||||
count_next[:] = n-1
|
||||
else:
|
||||
count_next[:] = cnt - 1
|
||||
return count_next
|
||||
|
||||
@always(clock.posedge, reset.negedge)
|
||||
def decFuncGen():
|
||||
if reset == ACTIVE_LOW:
|
||||
count.next = 0
|
||||
else:
|
||||
if enable:
|
||||
count.next = decFuncFunc(count)
|
||||
|
||||
return decFuncGen
|
||||
|
||||
|
||||
def decTask(count, enable, clock, reset, n):
|
||||
|
||||
def decTaskFunc(cnt, enable, reset, n):
|
||||
@ -163,14 +185,16 @@ class TestDec(TestCase):
|
||||
return sim
|
||||
|
||||
def testDecRef(self):
|
||||
""" Check decrement operation """
|
||||
sim = self.bench(decRef)
|
||||
sim.run(quiet=1)
|
||||
|
||||
def testDec(self):
|
||||
""" Check decrement operation """
|
||||
sim = self.bench(dec)
|
||||
sim.run(quiet=1)
|
||||
|
||||
def testDecFunc(self):
|
||||
sim = self.bench(decFunc)
|
||||
sim.run(quiet=1)
|
||||
|
||||
## signed inout in task doesn't work yet in Icarus
|
||||
## def testDecTask(self):
|
||||
|
@ -47,6 +47,21 @@ def inc(count, enable, clock, reset, n):
|
||||
count.next = (count + 1) % n
|
||||
return incProcess
|
||||
|
||||
def inc2(count, enable, clock, reset, n):
|
||||
|
||||
@always(clock.posedge, reset.negedge)
|
||||
def incProcess():
|
||||
if reset == ACTIVE_LOW:
|
||||
count.next = 0
|
||||
else:
|
||||
if enable:
|
||||
if count == n:
|
||||
count.next = 0
|
||||
else:
|
||||
count.next = count + 1
|
||||
return incProcess
|
||||
|
||||
|
||||
def incTask(count, enable, clock, reset, n):
|
||||
|
||||
def incTaskFunc(cnt, enable, reset, n):
|
||||
@ -155,6 +170,11 @@ class TestInc(TestCase):
|
||||
sim = self.bench(inc)
|
||||
sim.run(quiet=1)
|
||||
|
||||
def testInc2(self):
|
||||
""" Check increment operation """
|
||||
sim = self.bench(inc2)
|
||||
sim.run(quiet=1)
|
||||
|
||||
def testIncTask(self):
|
||||
sim = self.bench(incTask)
|
||||
sim.run(quiet=1)
|
||||
|
@ -482,6 +482,84 @@ class TestAugmOps(TestCase):
|
||||
Simulation(sim).run()
|
||||
|
||||
|
||||
def expressions(a, b, clk):
|
||||
|
||||
c = Signal(intbv(0, min=0, max=47))
|
||||
e = Signal(bool())
|
||||
|
||||
@instance
|
||||
def logic():
|
||||
|
||||
d = intbv(0, min=-23, max=43)
|
||||
d[:] = -17
|
||||
|
||||
c.next = 5
|
||||
yield clk.posedge
|
||||
a.next = c + 1
|
||||
b.next = c + 1
|
||||
yield clk.posedge
|
||||
a.next = c + -10
|
||||
b.next = c + -1
|
||||
yield clk.posedge
|
||||
a.next = c < -10
|
||||
b.next = c < -1
|
||||
yield clk.posedge
|
||||
a.next = d + c
|
||||
b.next = d >= c
|
||||
yield clk.posedge
|
||||
# a.next = d & c
|
||||
# b.next = c + (d & c)
|
||||
yield clk.posedge
|
||||
a.next = d + -c
|
||||
b.next = c + (-d)
|
||||
yield clk.posedge
|
||||
a.next = -d
|
||||
yield clk.posedge
|
||||
a.next = -c
|
||||
yield clk.posedge
|
||||
|
||||
|
||||
yield clk.posedge
|
||||
raise StopSimulation
|
||||
|
||||
return logic
|
||||
|
||||
def expressions_v(a, b, clk):
|
||||
return setupCosimulation(**locals())
|
||||
|
||||
|
||||
class TestExpressions(TestCase):
|
||||
|
||||
def bench(self):
|
||||
|
||||
a, a_v = [Signal(intbv(0, min=-34, max=47)) for i in range(2)]
|
||||
b, b_v = [Signal(intbv(0, min=0, max=47)) for i in range(2)]
|
||||
clk = Signal(bool())
|
||||
|
||||
expr = toVerilog(expressions, a, b, clk)
|
||||
expr_v = toVerilog(expressions, a_v, b_v, clk)
|
||||
|
||||
@instance
|
||||
def check():
|
||||
while 1:
|
||||
yield clk.posedge
|
||||
yield delay(1)
|
||||
self.assertEqual(a, a_v)
|
||||
# print a
|
||||
# print a_v
|
||||
self.assertEqual(b, b_v)
|
||||
|
||||
@always(delay(10))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
return expr, expr_v, check, clkgen
|
||||
|
||||
def testExpressions(self):
|
||||
sim = self.bench()
|
||||
Simulation(sim).run()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user