mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
simple always blocks to assign statements
non-local objects should be signals check
This commit is contained in:
parent
8225583303
commit
4f645619d4
@ -62,10 +62,11 @@ _error.UnsupportedListComp = \
|
|||||||
"Unsupported list comprehension form: should be [intbv()[n:] for i in range(m)]"
|
"Unsupported list comprehension form: should be [intbv()[n:] for i in range(m)]"
|
||||||
_error.ListElementAssign = \
|
_error.ListElementAssign = \
|
||||||
"Can't assign to list element; use slice assignment to change its value"
|
"Can't assign to list element; use slice assignment to change its value"
|
||||||
|
_error.NotASignal = "Non-local object should be a Signal"
|
||||||
|
|
||||||
|
|
||||||
_access = enum("INPUT", "OUTPUT", "INOUT", "UNKNOWN")
|
_access = enum("INPUT", "OUTPUT", "INOUT", "UNKNOWN")
|
||||||
_kind = enum("NORMAL", "DECLARATION", "ALWAYS", "INITIAL", "ALWAYS_COMB", "TASK")
|
_kind = enum("NORMAL", "DECLARATION", "ALWAYS", "INITIAL", "ALWAYS_COMB", "SIMPLE_ALWAYS_COMB", "TASK", "REG")
|
||||||
_context = enum("BOOLEAN", "YIELD", "PRINT", "UNKNOWN")
|
_context = enum("BOOLEAN", "YIELD", "PRINT", "UNKNOWN")
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ def _analyzeGens(top, genNames):
|
|||||||
s = inspect.getsource(f)
|
s = inspect.getsource(f)
|
||||||
s = s.lstrip()
|
s = s.lstrip()
|
||||||
ast = compiler.parse(s)
|
ast = compiler.parse(s)
|
||||||
#print ast
|
print ast
|
||||||
ast.sourcefile = inspect.getsourcefile(f)
|
ast.sourcefile = inspect.getsourcefile(f)
|
||||||
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
||||||
ast.symdict = f.func_globals.copy()
|
ast.symdict = f.func_globals.copy()
|
||||||
@ -110,7 +110,7 @@ def _analyzeGens(top, genNames):
|
|||||||
s = inspect.getsource(f)
|
s = inspect.getsource(f)
|
||||||
s = s.lstrip()
|
s = s.lstrip()
|
||||||
ast = compiler.parse(s)
|
ast = compiler.parse(s)
|
||||||
# print ast
|
print ast
|
||||||
ast.sourcefile = inspect.getsourcefile(f)
|
ast.sourcefile = inspect.getsourcefile(f)
|
||||||
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
||||||
ast.symdict = f.f_globals.copy()
|
ast.symdict = f.f_globals.copy()
|
||||||
@ -325,6 +325,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
node.obj = int()
|
node.obj = int()
|
||||||
|
|
||||||
def visitAssAttr(self, node, access=_access.OUTPUT, *args):
|
def visitAssAttr(self, node, access=_access.OUTPUT, *args):
|
||||||
|
if node.attrname != 'next':
|
||||||
|
self.raiseError(node, _error.NotSupported, "attribute assignment")
|
||||||
self.ast.kind = _kind.TASK
|
self.ast.kind = _kind.TASK
|
||||||
self.visit(node.expr, _access.OUTPUT)
|
self.visit(node.expr, _access.OUTPUT)
|
||||||
|
|
||||||
@ -544,6 +546,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
|||||||
self.ast.inputs.add(n)
|
self.ast.inputs.add(n)
|
||||||
elif access == _access.OUTPUT:
|
elif access == _access.OUTPUT:
|
||||||
self.ast.kind = _kind.TASK
|
self.ast.kind = _kind.TASK
|
||||||
|
if n in self.ast.outputs:
|
||||||
|
node.kind = _kind.REG
|
||||||
self.ast.outputs.add(n)
|
self.ast.outputs.add(n)
|
||||||
elif access == _access.UNKNOWN:
|
elif access == _access.UNKNOWN:
|
||||||
pass
|
pass
|
||||||
@ -650,7 +654,7 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
|||||||
s = self.ast.sigdict[n]
|
s = self.ast.sigdict[n]
|
||||||
if s._driven:
|
if s._driven:
|
||||||
self.raiseError(node, _error.SigMultipleDriven, n)
|
self.raiseError(node, _error.SigMultipleDriven, n)
|
||||||
s._driven = True
|
s._driven = "reg"
|
||||||
for n in self.ast.inputs:
|
for n in self.ast.inputs:
|
||||||
s = self.ast.sigdict[n]
|
s = self.ast.sigdict[n]
|
||||||
s._read = True
|
s._read = True
|
||||||
@ -668,18 +672,33 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
|||||||
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
|
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
|
||||||
|
|
||||||
def __init__(self, ast, senslist):
|
def __init__(self, ast, senslist):
|
||||||
_AnalyzeVisitor.__init__(self, ast)
|
_AnalyzeBlockVisitor.__init__(self, ast)
|
||||||
self.ast.senslist = senslist
|
self.ast.senslist = senslist
|
||||||
for n, v in self.ast.symdict.items():
|
|
||||||
if isinstance(v, Signal):
|
|
||||||
self.ast.sigdict[n] = v
|
|
||||||
|
|
||||||
def visitFunction(self, node, *args):
|
def visitFunction(self, node, *args):
|
||||||
self.refStack.push()
|
self.refStack.push()
|
||||||
self.visit(node.code)
|
self.visit(node.code)
|
||||||
|
self.ast.kind = _kind.SIMPLE_ALWAYS_COMB
|
||||||
|
for n in node.code.nodes:
|
||||||
|
if isinstance(n, astNode.Assign) and \
|
||||||
|
isinstance(n.nodes[0], astNode.AssAttr) and \
|
||||||
|
self.getKind(n.nodes[0].expr) != _kind.REG:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
self.ast.kind = _kind.ALWAYS_COMB
|
self.ast.kind = _kind.ALWAYS_COMB
|
||||||
|
return
|
||||||
self.refStack.pop()
|
self.refStack.pop()
|
||||||
|
|
||||||
|
def visitModule(self, node, *args):
|
||||||
|
_AnalyzeBlockVisitor.visitModule(self, node, *args)
|
||||||
|
if self.ast.kind == _kind.SIMPLE_ALWAYS_COMB:
|
||||||
|
for n in self.ast.outputs:
|
||||||
|
s = self.ast.sigdict[n]
|
||||||
|
s._driven = "wire"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class _AnalyzeFuncVisitor(_AnalyzeVisitor):
|
class _AnalyzeFuncVisitor(_AnalyzeVisitor):
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ def _writeModuleHeader(f, intf):
|
|||||||
r = _getRangeString(s)
|
r = _getRangeString(s)
|
||||||
if s._driven:
|
if s._driven:
|
||||||
print >> f, "output %s%s;" % (r, portname)
|
print >> f, "output %s%s;" % (r, portname)
|
||||||
print >> f, "reg %s%s;" % (r, portname)
|
print >> f, "%s %s%s;" % (s._driven, r, portname)
|
||||||
else:
|
else:
|
||||||
print >> f, "input %s%s;" % (r, portname)
|
print >> f, "input %s%s;" % (r, portname)
|
||||||
print >> f
|
print >> f
|
||||||
@ -137,8 +137,8 @@ def _writeSigDecls(f, intf, siglist):
|
|||||||
r = _getRangeString(s)
|
r = _getRangeString(s)
|
||||||
if s._driven:
|
if s._driven:
|
||||||
# the following line implements initial value assignments
|
# the following line implements initial value assignments
|
||||||
print >> f, "reg %s%s = %s;" % (r, s._name, int(s._val))
|
print >> f, "%s %s%s = %s;" % (s._driven, r, s._name, int(s._val))
|
||||||
# print >> f, "reg %s%s;" % (r, s._name)
|
# print >> f, "%s %s%s;" % (s._driven, r, s._name)
|
||||||
elif s._read:
|
elif s._read:
|
||||||
# the original exception
|
# the original exception
|
||||||
# raise ToVerilogError(_error.UndrivenSignal, s._name)
|
# raise ToVerilogError(_error.UndrivenSignal, s._name)
|
||||||
@ -210,6 +210,8 @@ def _convertGens(genlist, vfile):
|
|||||||
Visitor = _ConvertAlwaysVisitor
|
Visitor = _ConvertAlwaysVisitor
|
||||||
elif ast.kind == _kind.INITIAL:
|
elif ast.kind == _kind.INITIAL:
|
||||||
Visitor = _ConvertInitialVisitor
|
Visitor = _ConvertInitialVisitor
|
||||||
|
elif ast.kind == _kind.SIMPLE_ALWAYS_COMB:
|
||||||
|
Visitor = _ConvertSimpleAlwaysCombVisitor
|
||||||
else: # ALWAYS_COMB
|
else: # ALWAYS_COMB
|
||||||
Visitor = _ConvertAlwaysCombVisitor
|
Visitor = _ConvertAlwaysCombVisitor
|
||||||
v = Visitor(ast, blockBuf, funcBuf)
|
v = Visitor(ast, blockBuf, funcBuf)
|
||||||
@ -331,8 +333,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
|||||||
self.unaryOp(node, '-')
|
self.unaryOp(node, '-')
|
||||||
|
|
||||||
def visitAssAttr(self, node, *args):
|
def visitAssAttr(self, node, *args):
|
||||||
if node.attrname != 'next':
|
assert node.attrname == 'next'
|
||||||
self.raiseError(node, _error.NotSupported, "attribute assignment")
|
|
||||||
self.isSigAss = True
|
self.isSigAss = True
|
||||||
self.visit(node.expr)
|
self.visit(node.expr)
|
||||||
|
|
||||||
@ -398,7 +399,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
|||||||
return
|
return
|
||||||
elif f in (int, long):
|
elif f in (int, long):
|
||||||
opening, closing = '', ''
|
opening, closing = '', ''
|
||||||
elif type(f) in (ClassType, type) and issubclass(f, Exception):
|
elif type(f) is ClassType and issubclass(f, Exception):
|
||||||
self.write(f.__name__)
|
self.write(f.__name__)
|
||||||
elif f in (posedge, negedge):
|
elif f in (posedge, negedge):
|
||||||
opening, closing = ' ', ''
|
opening, closing = ' ', ''
|
||||||
@ -618,8 +619,10 @@ class _ConvertVisitor(_ToVerilogMixin):
|
|||||||
self.write(obj._name)
|
self.write(obj._name)
|
||||||
elif str(type(obj)) == "<class 'myhdl._enum.EnumItem'>":
|
elif str(type(obj)) == "<class 'myhdl._enum.EnumItem'>":
|
||||||
self.write(obj._toVerilog())
|
self.write(obj._toVerilog())
|
||||||
else:
|
elif type(obj) is ClassType and issubclass(obj, Exception):
|
||||||
self.write(n)
|
self.write(n)
|
||||||
|
else:
|
||||||
|
self.raiseError(node, _error.NotASignal, n)
|
||||||
else:
|
else:
|
||||||
raise AssertionError("name ref: %s" % n)
|
raise AssertionError("name ref: %s" % n)
|
||||||
|
|
||||||
@ -794,6 +797,21 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
|
|||||||
self.writeline(2)
|
self.writeline(2)
|
||||||
|
|
||||||
|
|
||||||
|
class _ConvertSimpleAlwaysCombVisitor(_ConvertVisitor):
|
||||||
|
|
||||||
|
def __init__(self, ast, blockBuf, funcBuf):
|
||||||
|
_ConvertVisitor.__init__(self, ast, blockBuf)
|
||||||
|
self.funcBuf = funcBuf
|
||||||
|
|
||||||
|
def visitAssAttr(self, node, *args):
|
||||||
|
self.write("assign ")
|
||||||
|
self.visit(node.expr)
|
||||||
|
|
||||||
|
def visitFunction(self, node, *args):
|
||||||
|
self.visit(node.code)
|
||||||
|
self.writeline()
|
||||||
|
|
||||||
|
|
||||||
class _ConvertFunctionVisitor(_ConvertVisitor):
|
class _ConvertFunctionVisitor(_ConvertVisitor):
|
||||||
|
|
||||||
def __init__(self, ast, funcBuf):
|
def __init__(self, ast, funcBuf):
|
||||||
|
@ -28,12 +28,14 @@ import unittest
|
|||||||
|
|
||||||
import test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
import test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
||||||
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
||||||
test_RandomScrambler, test_beh, test_GrayInc, test_misc
|
test_RandomScrambler, test_beh, test_GrayInc, test_misc, \
|
||||||
|
test_memory
|
||||||
|
|
||||||
|
|
||||||
modules = (test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
modules = (test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
||||||
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
test_inc_initial, test_hec, test_loops, test_infer, test_errors, \
|
||||||
test_RandomScrambler, test_beh, test_GrayInc, test_misc
|
test_RandomScrambler, test_beh, test_GrayInc, test_misc, \
|
||||||
|
test_memory
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,25 @@ def ram(dout, din, addr, we, clk, depth=128):
|
|||||||
# a[2] = din
|
# a[2] = din
|
||||||
dout.next = mem[int(addr)]
|
dout.next = mem[int(addr)]
|
||||||
|
|
||||||
|
|
||||||
|
def ram2(dout, din, addr, we, clk, depth=128):
|
||||||
|
|
||||||
|
memL = [intbv(0,min=dout._min,max=dout._max) for i in range(depth)]
|
||||||
|
def wrLogic() :
|
||||||
|
while 1:
|
||||||
|
yield posedge(clk)
|
||||||
|
if we:
|
||||||
|
memL[int(addr)][:] = din
|
||||||
|
|
||||||
|
def rdLogic() :
|
||||||
|
while 1:
|
||||||
|
yield posedge(clk)
|
||||||
|
dout.next = memL[int(addr)]
|
||||||
|
|
||||||
|
WL = wrLogic()
|
||||||
|
RL = rdLogic()
|
||||||
|
return WL,RL
|
||||||
|
|
||||||
objfile = "mem.o"
|
objfile = "mem.o"
|
||||||
analyze_cmd = "iverilog -o %s mem_inst.v tb_mem_inst.v" % objfile
|
analyze_cmd = "iverilog -o %s mem_inst.v tb_mem_inst.v" % objfile
|
||||||
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
|
simulate_cmd = "vvp -m ../../../cosimulation/icarus/myhdl.vpi %s" % objfile
|
||||||
@ -32,7 +51,7 @@ def ram_v(dout, din, addr, we, clk, depth=4):
|
|||||||
|
|
||||||
class TestMemory(TestCase):
|
class TestMemory(TestCase):
|
||||||
|
|
||||||
def bench(self, depth=128):
|
def bench(self, ram, depth=128):
|
||||||
|
|
||||||
dout = Signal(intbv(0)[8:])
|
dout = Signal(intbv(0)[8:])
|
||||||
dout_v = Signal(intbv(0)[8:])
|
dout_v = Signal(intbv(0)[8:])
|
||||||
@ -68,8 +87,12 @@ class TestMemory(TestCase):
|
|||||||
|
|
||||||
return clkgen(), stimulus(), mem_inst, mem_v_inst
|
return clkgen(), stimulus(), mem_inst, mem_v_inst
|
||||||
|
|
||||||
def test(self):
|
## def test1(self):
|
||||||
sim = self.bench()
|
## sim = self.bench(ram)
|
||||||
|
## Simulation(sim).run()
|
||||||
|
|
||||||
|
def test2(self):
|
||||||
|
sim = self.bench(ram2)
|
||||||
Simulation(sim).run()
|
Simulation(sim).run()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user