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 = s.lstrip()
|
||||
ast = compiler.parse(s)
|
||||
print ast
|
||||
fname = f.__name__
|
||||
ast.name = _Label(fname)
|
||||
ast.sourcefile = inspect.getsourcefile(f)
|
||||
@ -403,8 +404,6 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
self.visit(arg, _access.OUTPUT)
|
||||
if n in ast.inputs:
|
||||
self.visit(arg, _access.INPUT)
|
||||
if ast.isGen:
|
||||
self.raiseError(node, _error.NotSupported, "Generator function call")
|
||||
elif type(f) is MethodType:
|
||||
self.raiseError(node,_error.NotSupported, "method call: '%s'" % f.__name__)
|
||||
else:
|
||||
@ -610,8 +609,13 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
||||
|
||||
def visitReturn(self, node, *args):
|
||||
### 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):
|
||||
|
||||
@ -653,17 +657,29 @@ class _AnalyzeFuncVisitor(_AnalyzeVisitor):
|
||||
self.ast.sigdict[n] = v
|
||||
self.visit(node.code)
|
||||
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):
|
||||
self.visit(node.value, _access.INPUT, _kind.DECLARATION, *args)
|
||||
if isinstance(node.value, astNode.Const) and node.value.value is 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
|
||||
elif node.value.obj is not None:
|
||||
obj = node.value.obj
|
||||
else:
|
||||
self.raiseError(node, error._ReturnTypeInfer)
|
||||
self.raiseError(node, _error.ReturnTypeInfer)
|
||||
if isinstance(obj, intbv) and len(obj) == 0:
|
||||
self.raiseError(node, _error.ReturnIntbvBitWidth)
|
||||
if self.ast.hasReturn:
|
||||
|
@ -181,15 +181,15 @@ class TestNotSupported(unittest.TestCase):
|
||||
## z.next = 2 ** 8
|
||||
## self.check(g, z, a)
|
||||
|
||||
def testReturn(self):
|
||||
a = Signal(bool())
|
||||
z = Signal(bool())
|
||||
def g(z, a):
|
||||
while 1:
|
||||
yield a
|
||||
z.next = 1
|
||||
return
|
||||
self.check(g, z, a)
|
||||
## def testReturn(self):
|
||||
## a = Signal(bool())
|
||||
## z = Signal(bool())
|
||||
## def g(z, a):
|
||||
## while 1:
|
||||
## yield a
|
||||
## z.next = 1
|
||||
## return
|
||||
## self.check(g, z, a)
|
||||
|
||||
def testTryExcept(self):
|
||||
a = Signal(bool())
|
||||
|
@ -84,7 +84,7 @@ def RandomScrambler_v(o7, o6, o5, o4, o3, o2, o1, o0,
|
||||
return Cosimulation(simulate_cmd, **locals())
|
||||
|
||||
|
||||
class TestRandomScramber(TestCase):
|
||||
class TestRandomScrambler(TestCase):
|
||||
|
||||
def stimulus(self):
|
||||
input = intbv()
|
||||
|
@ -11,55 +11,6 @@ from myhdl._toVerilog import ToVerilogError, _error
|
||||
|
||||
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):
|
||||
cnt = intbv(0)[8:]
|
||||
@ -166,19 +117,46 @@ def recursion2(count, enable, clock, reset, n):
|
||||
else:
|
||||
if enable:
|
||||
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"
|
||||
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
|
||||
|
||||
def inc_v(count, enable, clock, reset):
|
||||
def err_v(count, enable, clock, reset):
|
||||
if path.exists(objfile):
|
||||
os.remove(objfile)
|
||||
os.system(analyze_cmd)
|
||||
return Cosimulation(simulate_cmd, **locals())
|
||||
|
||||
class TestInc(TestCase):
|
||||
class TestErr(TestCase):
|
||||
|
||||
def clockGen(self, clock):
|
||||
while 1:
|
||||
@ -213,7 +191,7 @@ class TestInc(TestCase):
|
||||
self.assertEqual(count, expect)
|
||||
self.assertEqual(count, count_v)
|
||||
|
||||
def bench(self, inc):
|
||||
def bench(self, err):
|
||||
|
||||
m = 8
|
||||
n = 2 ** m
|
||||
@ -223,28 +201,14 @@ class TestInc(TestCase):
|
||||
enable = Signal(bool(0))
|
||||
clock, reset = [Signal(bool()) for i in range(2)]
|
||||
|
||||
inc_inst_ref = incRef(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)
|
||||
err_inst = toVerilog(err, count, enable, clock, reset, n=n)
|
||||
clk_1 = self.clockGen(clock)
|
||||
st_1 = self.stimulus(enable, clock, reset)
|
||||
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
|
||||
|
||||
## 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):
|
||||
try:
|
||||
@ -309,6 +273,22 @@ class TestInc(TestCase):
|
||||
self.assertEqual(e.kind, _error.NotSupported)
|
||||
else:
|
||||
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__':
|
||||
|
Loading…
x
Reference in New Issue
Block a user