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

infer check

This commit is contained in:
jand 2003-12-04 22:31:14 +00:00
parent 6d797db44f
commit beaca96d74
3 changed files with 288 additions and 19 deletions

View File

@ -59,6 +59,11 @@ _error.SigMultipleDriven = "Signal has multiple drivers"
_error.UndefinedBitWidth = "Signal has undefined bit width"
_error.UndrivenSignal = "Signal is not driven"
_error.Requirement = "Requirement violation"
_error.UnboundLocal="Local variable may be referenced before assignment"
_error.TypeMismatch="Type mismatch with earlier assignment"
_error.NrBitsMismatch="Nr of bits mismatch with earlier assignment"
_error.ReturnTypeMismatch="Return type mismatch"
_error.ReutrnNrBitsMismatch="Returned nr of bits mismatch"
def _checkArgs(arglist):
for arg in arglist:
@ -299,6 +304,19 @@ def getNrBits(obj):
return obj._nrbits
return None
class ReferenceStack(list):
def push(self):
self.append(Set())
def add(self, item):
self[-1].add(item)
def __contains__(self, item):
for s in self:
if item in s:
return True
return False
class _AnalyzeVisitor(_ToVerilogMixin):
def __init__(self, symdict, sourcefile, lineoffset):
@ -310,6 +328,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
self.outputs = Set()
self.used = Set()
self.labelStack = []
self.refStack = ReferenceStack()
self.globalRefs = Set()
def getObj(self, node):
if hasattr(node, 'obj'):
@ -346,19 +366,27 @@ class _AnalyzeVisitor(_ToVerilogMixin):
obj = self.getObj(expr)
if obj is None:
self.raiseError(node, "Cannot infer type or bit width of %s" % n)
if n in self.vardict:
curObj = self.vardict[n]
if isinstance(obj, type(curObj)):
pass
elif isinstance(curObj, type(obj)):
self.vardict[n] = obj
else:
self.raiseError(node, _error.TypeMismatch, n)
if getNrBits(obj) != getNrBits(curObj):
self.raiseError(node, _error.NrBitsMismatch, n)
else:
self.vardict[n] = obj
# XXX if n is already in vardict
else:
self.visit(expr, INPUT)
def visitAssName(self, node, *args):
n = node.name
# XXX ?
if n in self.vardict:
return
if n in self.used:
self.require(node, n not in self.symdict,
"Previously used external symbol cannot be locally redeclared: %s" % n)
if n in self.globalRefs:
self.raiseError(node, _error.UnboundLocal, n)
self.refStack.add(n)
def visitAugAssign(self, node, access=INPUT, *args):
self.visit(node.node, INOUT)
@ -377,6 +405,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
node.obj = intbv()
elif func is len:
node.obj = int() # XXX
elif func is bool:
node.obj = bool()
elif func in myhdl.__dict__.values():
pass
elif func in __builtin__.__dict__.values():
@ -422,9 +452,9 @@ class _AnalyzeVisitor(_ToVerilogMixin):
node.obj = bool()
def visitConst(self, node, *args):
if isinstance(node.value, bool):
node.obj = bool()
elif isinstance(node.value, int):
## if isinstance(node.value, bool): # bool constants are names ???
## node.obj = bool()
if isinstance(node.value, int):
node.obj = int()
else:
node.obj = None
@ -437,11 +467,13 @@ class _AnalyzeVisitor(_ToVerilogMixin):
node.loopLabel = Label("LOOP")
self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel)
self.refStack.push()
self.visit(node.assign)
var = node.assign.name
self.vardict[var] = int()
self.visit(node.list)
self.visit(node.body, *args)
self.refStack.pop()
self.require(node, node.else_ is None, "for-else not supported")
self.labelStack.pop()
self.labelStack.pop()
@ -458,9 +490,24 @@ class _AnalyzeVisitor(_ToVerilogMixin):
assert hasattr(obj, node.attrname)
node.obj = getattr(obj, node.attrname)
def visitIf(self, node, *args):
for test, suite in node.tests:
self.visit(test, *args)
self.refStack.push()
self.visit(suite, *args)
self.refStack.pop()
if node.else_:
self.refStack.push()
self.visit(node.else_, *args)
self.refStack.pop()
def visitName(self, node, access=INPUT, *args):
n = node.name
self.used.add(n)
if n not in self.refStack:
if n in self.vardict:
self.raiseError(node, _error.UnboundLocal, n)
self.globalRefs.add(n)
if n in self.sigdict:
if access == INPUT:
self.inputs.add(n)
@ -475,8 +522,10 @@ class _AnalyzeVisitor(_ToVerilogMixin):
node.obj = self.vardict[n]
elif n in self.symdict:
node.obj = self.symdict[n]
else:
elif n in __builtin__.__dict__:
node.obj = __builtins__[n]
else:
pass
def visitReturn(self, node, *args):
self.visit(node.value)
@ -511,7 +560,9 @@ class _AnalyzeVisitor(_ToVerilogMixin):
self.labelStack.append(node.breakLabel)
self.labelStack.append(node.loopLabel)
self.visit(node.test, *args)
self.refStack.push()
self.visit(node.body, *args)
self.refStack.pop()
if isinstance(node.test, ast.Const) and \
node.test.value == True and \
isinstance(node.body.nodes[0], ast.Yield):
@ -531,6 +582,7 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
sigdict[n] = v
def visitFunction(self, node, *args):
self.refStack.push()
print node.code
self.visit(node.code)
self.kind = ALWAYS
@ -542,6 +594,7 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
w = node.code.nodes[-1]
if not self.getKind(w) == ALWAYS:
self.kind = INITIAL
self.refStack.pop()
def visitModule(self, node, *args):
self.visit(node.node)
@ -571,6 +624,7 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
self.returnObj = None
def visitFunction(self, node, *args):
self.refStack.push()
argnames = node.argnames
for i, arg in enumerate(self.args):
if isinstance(arg, ast.Keyword):
@ -584,7 +638,7 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
if isinstance(v, (Signal, intbv)):
self.sigdict[n] = v
self.visit(node.code)
self.refStack.pop()
def visitReturn(self, node, *args):
self.visit(node.value)
@ -598,14 +652,14 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
self.raiseError(node, "Can't derive return type")
if self.hasReturn:
returnObj = self.returnObj
if getNrBits(obj) != getNrBits(returnObj):
self.raiseError(node, "Returned nr of bits is different from before")
if isinstance(obj, type(returnObj)):
pass
elif isinstance(returnObj, type(obj)):
self.returnObj = type(obj)
self.returnObj = obj
else:
self.raiseError(node, "Incompatible return type")
self.raiseError(node, _error.ReturnTypeMismatch)
if getNrBits(obj) != getNrBits(returnObj):
self.raiseError(node, _error.ReturnNrBitsMismatch)
else:
self.returnObj = obj
self.hasReturn = True
@ -664,7 +718,7 @@ def _writeModuleHeader(f, intf):
if s._driven:
print >> f, "output %s%s;" % (r, portname)
print >> f, "reg %s%s;" % (r, portname)
elif s._read:
else:
print >> f, "input %s%s;" % (r, portname)
print >> f
@ -1060,7 +1114,11 @@ class _ConvertVisitor(_ToVerilogMixin):
def visitName(self, node):
n = node.name
if n in self.vardict:
if n == 'False':
self.write("1'b0")
elif n == 'True':
self.write("1'b1")
elif n in self.vardict:
self.write(n)
elif node.name in self.symdict:
obj = self.symdict[n]
@ -1163,7 +1221,6 @@ class _ConvertVisitor(_ToVerilogMixin):
def visitYield(self, node):
self.inYield = True
self.writeline()
self.write("@ (")
self.visit(node.value)
self.write(");")
@ -1230,6 +1287,8 @@ class _ConvertFunctionVisitor(_ConvertVisitor):
elif hasattr(obj, '_nrbits'):
self.write("[%s-1:0]" % obj._nrbits)
else:
print "HERE"
print type(obj)
raise AssertionError("unexpected type")
def writeInputDeclarations(self):

View File

@ -73,6 +73,7 @@ def FramerCtrl_alt(SOF, state, syncFlag, clk, reset_n):
def FSM():
index = intbv(0)[8:] # position in frame
state_var = t_State.SEARCH
while 1:
yield posedge(clk), negedge(reset_n)
if reset_n == ACTIVE_LOW:

View File

@ -0,0 +1,209 @@
import os
path = os.path
import unittest
from random import randrange
from myhdl import *
from myhdl._toVerilog import ToVerilogError, _error
b = c = 2
def UnboundError1(a, out):
while 1:
yield a
out.next = a + b
b = 1
def UnboundError2(a, out):
while 1:
yield a
if a == 1:
c = 1
else:
out.next = c
def UnboundError3(a, out):
while 1:
yield a
out.next = a + d
d = 1
def UnboundError4(a, out):
while 1:
yield a
if a == 1:
e = 1
else:
out.next = e
def InferError1(a, out):
yield a
b = 2
b = intbv(0)[5:]
b[:] = 4
out.next = b
def InferError2(a, out):
yield a
c = intbv(0)[5:]
c[:] = 4
c = intbv(0)[4:]
c[:] = 4
out.next = c
enumType = enum("a", "b", "c")
def InferError3(a, out):
yield a
d = enumType.a
d = 4
out.next = b
class TestErrors(unittest.TestCase):
def check(self, *args):
try:
i = toVerilog(*args)
except ToVerilogError, e:
self.assertEqual(e.kind, _error.NotSupported)
except:
self.fail()
else:
self.fail()
def check(self, Infertest, err):
a = Signal(intbv(-1)[16:])
out_v = Signal(intbv(0)[16:])
out = Signal(intbv(0)[16:])
try:
infertest_inst = toVerilog(Infertest, a, out)
except ToVerilogError, e:
self.assertEqual(e.kind, err)
except:
self.fail()
else:
self.fail()
def nocheck(self, Infertest, err=None):
a = Signal(intbv(-1)[16:])
out_v = Signal(intbv(0)[16:])
out = Signal(intbv(0)[16:])
infertest_inst = toVerilog(Infertest, a, out)
def testUnboundError1(self):
sim = self.check(UnboundError1, _error.UnboundLocal)
def testUnboundError2(self):
sim = self.check(UnboundError2, _error.UnboundLocal)
def testUnboundError3(self):
sim = self.check(UnboundError3, _error.UnboundLocal)
def testUnboundError4(self):
sim = self.check(UnboundError4, _error.UnboundLocal)
def testInferError1(self):
sim = self.check(InferError1, _error.TypeMismatch)
def testInferError2(self):
sim = self.check(InferError2, _error.NrBitsMismatch)
def testInferError3(self):
sim = self.check(InferError3, _error.TypeMismatch)
def Infer1(a, out):
yield a
c = 5
c = a < 4
c = bool(0)
c = False
c = True
out.next = c
def Infer2(a, out):
yield a
c = a < 4
c = bool(0)
c = False
c = True
c = 5
out.next = c
def Infer3Func(a):
if True:
return a > 0
else:
return 5
def Infer3(a, out):
yield a
out.next = Infer3Func(a)
def Infer4Func(a):
if True:
return 6
else:
return a < 3
def Infer4(a, out):
yield a
out.next = Infer4Func(a)
objfile = "infertest.o"
analyze_cmd = "iverilog -o %s infertest_inst.v tb_infertest_inst.v" % objfile
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
def Infertest_v(a, out):
if path.exists(objfile):
os.remove(objfile)
os.system(analyze_cmd)
return Cosimulation(simulate_cmd, **locals())
class TestInfer(unittest.TestCase):
def bench(self, Infertest):
a = Signal(intbv(-1)[16:])
out_v = Signal(intbv(0)[16:])
out = Signal(intbv(0)[16:])
infertest_inst = toVerilog(Infertest, a, out)
# infertest_inst = Infertest(hec, header)
infertest_v_inst = Infertest_v(a, out_v)
def stimulus():
a.next = 1
yield delay(10)
print "%s %s" % (out, out_v)
self.assertEqual(out, out_v)
return stimulus(), infertest_inst, infertest_v_inst
## def testInfer1(self):
## sim = self.bench(Infer1)
## Simulation(sim).run()
## def testInfer2(self):
## sim = self.bench(Infer2)
## Simulation(sim).run()
## def testInfer3(self):
## sim = self.bench(Infer3)
## Simulation(sim).run()
def testInfer4(self):
sim = self.bench(Infer4)
Simulation(sim).run()
if __name__ == '__main__':
unittest.main()