mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
function / task check
This commit is contained in:
parent
5d1e8fe952
commit
530e65c559
@ -373,6 +373,7 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
s = inspect.getsource(f)
|
s = inspect.getsource(f)
|
||||||
s = s.lstrip()
|
s = s.lstrip()
|
||||||
ast = compiler.parse(s)
|
ast = compiler.parse(s)
|
||||||
|
print ast
|
||||||
fname = f.__name__
|
fname = f.__name__
|
||||||
ast.name = _Label(fname)
|
ast.name = _Label(fname)
|
||||||
ast.sourcefile = inspect.getsourcefile(f)
|
ast.sourcefile = inspect.getsourcefile(f)
|
||||||
@ -403,8 +404,6 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
self.visit(arg, _access.OUTPUT)
|
self.visit(arg, _access.OUTPUT)
|
||||||
if n in ast.inputs:
|
if n in ast.inputs:
|
||||||
self.visit(arg, _access.INPUT)
|
self.visit(arg, _access.INPUT)
|
||||||
if ast.isGen:
|
|
||||||
self.raiseError(node, _error.NotSupported, "Generator function call")
|
|
||||||
elif type(f) is MethodType:
|
elif type(f) is MethodType:
|
||||||
self.raiseError(node,_error.NotSupported, "method call: '%s'" % f.__name__)
|
self.raiseError(node,_error.NotSupported, "method call: '%s'" % f.__name__)
|
||||||
else:
|
else:
|
||||||
@ -610,8 +609,13 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
|||||||
|
|
||||||
def visitReturn(self, node, *args):
|
def visitReturn(self, node, *args):
|
||||||
### value should be None
|
### value should be None
|
||||||
self.raiseError(node, _error.NotSupported, "return statement")
|
if isinstance(node.value, astNode.Const) and node.value.value is None:
|
||||||
|
obj = None
|
||||||
|
elif isinstance(node.value, astNode.Name) and node.value.name == 'None':
|
||||||
|
obj = None
|
||||||
|
else:
|
||||||
|
self.raiseError(node, _error.NotSupported, "return value other than None")
|
||||||
|
|
||||||
|
|
||||||
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
|
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
|
||||||
|
|
||||||
@ -653,17 +657,29 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
|
|||||||
self.ast.sigdict[n] = v
|
self.ast.sigdict[n] = v
|
||||||
self.visit(node.code)
|
self.visit(node.code)
|
||||||
self.refStack.pop()
|
self.refStack.pop()
|
||||||
|
if self.ast.isGen:
|
||||||
|
self.raiseError(node, _error.NotSupported,
|
||||||
|
"call to a generator function")
|
||||||
|
if self.ast.kind == _kind.TASK:
|
||||||
|
if self.ast.returnObj is not None:
|
||||||
|
self.raiseError(node, _error.NotSupported,
|
||||||
|
"function with side effects and return value")
|
||||||
|
else:
|
||||||
|
if self.ast.returnObj is None:
|
||||||
|
self.raiseError(node, _error.NotSupported,
|
||||||
|
"pure function without return value")
|
||||||
|
|
||||||
|
|
||||||
def visitReturn(self, node, *args):
|
def visitReturn(self, node, *args):
|
||||||
self.visit(node.value, _access.INPUT, _kind.DECLARATION, *args)
|
self.visit(node.value, _access.INPUT, _kind.DECLARATION, *args)
|
||||||
if isinstance(node.value, astNode.Const) and node.value.value is None:
|
if isinstance(node.value, astNode.Const) and node.value.value is None:
|
||||||
obj = None
|
obj = None
|
||||||
elif isinstance(node.value, astNode.Name) and node.value.name is None:
|
elif isinstance(node.value, astNode.Name) and node.value.name == 'None':
|
||||||
obj = None
|
obj = None
|
||||||
elif node.value.obj is not None:
|
elif node.value.obj is not None:
|
||||||
obj = node.value.obj
|
obj = node.value.obj
|
||||||
else:
|
else:
|
||||||
self.raiseError(node, error._ReturnTypeInfer)
|
self.raiseError(node, _error.ReturnTypeInfer)
|
||||||
if isinstance(obj, intbv) and len(obj) == 0:
|
if isinstance(obj, intbv) and len(obj) == 0:
|
||||||
self.raiseError(node, _error.ReturnIntbvBitWidth)
|
self.raiseError(node, _error.ReturnIntbvBitWidth)
|
||||||
if self.ast.hasReturn:
|
if self.ast.hasReturn:
|
||||||
|
@ -181,15 +181,15 @@ class TestNotSupported(unittest.TestCase):
|
|||||||
## z.next = 2 ** 8
|
## z.next = 2 ** 8
|
||||||
## self.check(g, z, a)
|
## self.check(g, z, a)
|
||||||
|
|
||||||
def testReturn(self):
|
## def testReturn(self):
|
||||||
a = Signal(bool())
|
## a = Signal(bool())
|
||||||
z = Signal(bool())
|
## z = Signal(bool())
|
||||||
def g(z, a):
|
## def g(z, a):
|
||||||
while 1:
|
## while 1:
|
||||||
yield a
|
## yield a
|
||||||
z.next = 1
|
## z.next = 1
|
||||||
return
|
## return
|
||||||
self.check(g, z, a)
|
## self.check(g, z, a)
|
||||||
|
|
||||||
def testTryExcept(self):
|
def testTryExcept(self):
|
||||||
a = Signal(bool())
|
a = Signal(bool())
|
||||||
|
@ -84,7 +84,7 @@ def RandomScrambler_v(o7, o6, o5, o4, o3, o2, o1, o0,
|
|||||||
return Cosimulation(simulate_cmd, **locals())
|
return Cosimulation(simulate_cmd, **locals())
|
||||||
|
|
||||||
|
|
||||||
class TestRandomScramber(TestCase):
|
class TestRandomScrambler(TestCase):
|
||||||
|
|
||||||
def stimulus(self):
|
def stimulus(self):
|
||||||
input = intbv()
|
input = intbv()
|
||||||
|
@ -11,55 +11,6 @@ from myhdl._toVerilog import ToVerilogError, _error
|
|||||||
|
|
||||||
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
ACTIVE_LOW, INACTIVE_HIGH = 0, 1
|
||||||
|
|
||||||
def incRef(count, enable, clock, reset, n):
|
|
||||||
""" Incrementer with enable.
|
|
||||||
|
|
||||||
count -- output
|
|
||||||
enable -- control input, increment when 1
|
|
||||||
clock -- clock input
|
|
||||||
reset -- asynchronous reset input
|
|
||||||
n -- counter max value
|
|
||||||
"""
|
|
||||||
while 1:
|
|
||||||
yield posedge(clock), negedge(reset)
|
|
||||||
if reset == ACTIVE_LOW:
|
|
||||||
count.next = 0
|
|
||||||
else:
|
|
||||||
if enable:
|
|
||||||
count.next = (count + 1) % n
|
|
||||||
|
|
||||||
## def incTaskFunc(count, count_in, enable, clock, reset, n):
|
|
||||||
## if enable:
|
|
||||||
## count.next = (count_in + 1) % n
|
|
||||||
|
|
||||||
## def incTask(count, enable, clock, reset, n):
|
|
||||||
## while 1:
|
|
||||||
## yield posedge(clock), negedge(reset)
|
|
||||||
## if reset == ACTIVE_LOW:
|
|
||||||
## count.next = 0
|
|
||||||
## else:
|
|
||||||
## incTaskFunc(count, count, enable, clock, reset, n)
|
|
||||||
|
|
||||||
## def incTask(count, enable, clock, reset, n):
|
|
||||||
|
|
||||||
## def incTaskFunc(cnt, enable, reset, n):
|
|
||||||
## if enable:
|
|
||||||
## cnt[:] = (cnt + 1) % n
|
|
||||||
|
|
||||||
## def incTaskGen():
|
|
||||||
## cnt = intbv(0)[8:]
|
|
||||||
## while 1:
|
|
||||||
## yield posedge(clock), negedge(reset)
|
|
||||||
## if reset == ACTIVE_LOW:
|
|
||||||
## cnt[:] = 0
|
|
||||||
## count.next = 0
|
|
||||||
## else:
|
|
||||||
## # print count
|
|
||||||
## incTaskFunc(cnt, enable, reset, n)
|
|
||||||
## count.next = cnt
|
|
||||||
|
|
||||||
## return incTaskGen()
|
|
||||||
|
|
||||||
|
|
||||||
def freeVarTypeError(count, enable, clock, reset, n):
|
def freeVarTypeError(count, enable, clock, reset, n):
|
||||||
cnt = intbv(0)[8:]
|
cnt = intbv(0)[8:]
|
||||||
@ -166,19 +117,46 @@ def recursion2(count, enable, clock, reset, n):
|
|||||||
else:
|
else:
|
||||||
if enable:
|
if enable:
|
||||||
count.next = f2(n)
|
count.next = f2(n)
|
||||||
|
|
||||||
|
def h1(n):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def functionNoReturnVal(count, enable, clock, reset, n):
|
||||||
|
while 1:
|
||||||
|
yield posedge(clock), negedge(reset)
|
||||||
|
if reset == ACTIVE_LOW:
|
||||||
|
count.next = 0
|
||||||
|
else:
|
||||||
|
if enable:
|
||||||
|
count.next = h1(n)
|
||||||
|
|
||||||
|
def h2(cnt):
|
||||||
|
cnt[:] = cnt + 1
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def taskReturnVal(count, enable, clock, reset, n):
|
||||||
|
cnt = intbv()[8:]
|
||||||
|
while 1:
|
||||||
|
yield posedge(clock), negedge(reset)
|
||||||
|
if reset == ACTIVE_LOW:
|
||||||
|
count.next = 0
|
||||||
|
else:
|
||||||
|
if enable:
|
||||||
|
h2(cnt)
|
||||||
|
count.next = count + 1
|
||||||
|
|
||||||
|
|
||||||
objfile = "inc_inst.o"
|
objfile = "inc_inst.o"
|
||||||
analyze_cmd = "iverilog -o %s inc_inst.v tb_inc_inst.v" % objfile
|
analyze_cmd = "iverilog -o %s err_inst.v tb_err_inst.v" % objfile
|
||||||
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
|
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
|
||||||
|
|
||||||
def inc_v(count, enable, clock, reset):
|
def err_v(count, enable, clock, reset):
|
||||||
if path.exists(objfile):
|
if path.exists(objfile):
|
||||||
os.remove(objfile)
|
os.remove(objfile)
|
||||||
os.system(analyze_cmd)
|
os.system(analyze_cmd)
|
||||||
return Cosimulation(simulate_cmd, **locals())
|
return Cosimulation(simulate_cmd, **locals())
|
||||||
|
|
||||||
class TestInc(TestCase):
|
class TestErr(TestCase):
|
||||||
|
|
||||||
def clockGen(self, clock):
|
def clockGen(self, clock):
|
||||||
while 1:
|
while 1:
|
||||||
@ -213,7 +191,7 @@ class TestInc(TestCase):
|
|||||||
self.assertEqual(count, expect)
|
self.assertEqual(count, expect)
|
||||||
self.assertEqual(count, count_v)
|
self.assertEqual(count, count_v)
|
||||||
|
|
||||||
def bench(self, inc):
|
def bench(self, err):
|
||||||
|
|
||||||
m = 8
|
m = 8
|
||||||
n = 2 ** m
|
n = 2 ** m
|
||||||
@ -223,28 +201,14 @@ class TestInc(TestCase):
|
|||||||
enable = Signal(bool(0))
|
enable = Signal(bool(0))
|
||||||
clock, reset = [Signal(bool()) for i in range(2)]
|
clock, reset = [Signal(bool()) for i in range(2)]
|
||||||
|
|
||||||
inc_inst_ref = incRef(count, enable, clock, reset, n=n)
|
err_inst = toVerilog(err, count, enable, clock, reset, n=n)
|
||||||
inc_inst = toVerilog(inc, count, enable, clock, reset, n=n)
|
|
||||||
inc_inst_v = inc_v(count_v, enable, clock, reset)
|
|
||||||
clk_1 = self.clockGen(clock)
|
clk_1 = self.clockGen(clock)
|
||||||
st_1 = self.stimulus(enable, clock, reset)
|
st_1 = self.stimulus(enable, clock, reset)
|
||||||
ch_1 = self.check(count, count_v, enable, clock, reset, n=n)
|
ch_1 = self.check(count, count_v, enable, clock, reset, n=n)
|
||||||
|
|
||||||
sim = Simulation(inc_inst_ref, inc_inst_v, clk_1, st_1, ch_1)
|
sim = Simulation(err_inst, clk_1, st_1, ch_1)
|
||||||
return sim
|
return sim
|
||||||
|
|
||||||
## def testIncRef(self):
|
|
||||||
## """ Check increment operation """
|
|
||||||
## sim = self.bench(incRef)
|
|
||||||
## sim.run(quiet=1)
|
|
||||||
|
|
||||||
## def testIncTask(self):
|
|
||||||
## sim = self.bench(incTask)
|
|
||||||
## sim.run(quiet=1)
|
|
||||||
|
|
||||||
## def testIncTaskFreeVar(self):
|
|
||||||
## sim = self.bench(incTaskFreeVar)
|
|
||||||
## sim.run(quiet=1)
|
|
||||||
|
|
||||||
def testInternalSignal(self):
|
def testInternalSignal(self):
|
||||||
try:
|
try:
|
||||||
@ -309,6 +273,22 @@ class TestInc(TestCase):
|
|||||||
self.assertEqual(e.kind, _error.NotSupported)
|
self.assertEqual(e.kind, _error.NotSupported)
|
||||||
else:
|
else:
|
||||||
self.fail()
|
self.fail()
|
||||||
|
|
||||||
|
def testFunctionNoReturnVal(self):
|
||||||
|
try:
|
||||||
|
self.bench(functionNoReturnVal)
|
||||||
|
except ToVerilogError, e:
|
||||||
|
self.assertEqual(e.kind, _error.NotSupported)
|
||||||
|
else:
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
def testTaskReturnVal(self):
|
||||||
|
try:
|
||||||
|
self.bench(taskReturnVal)
|
||||||
|
except ToVerilogError, e:
|
||||||
|
self.assertEqual(e.kind, _error.NotSupported)
|
||||||
|
else:
|
||||||
|
self.fail()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user