mirror of
https://github.com/myhdl/myhdl.git
synced 2024-12-14 07:44:38 +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)]"
|
||||
_error.ListElementAssign = \
|
||||
"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")
|
||||
_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")
|
||||
|
||||
|
||||
|
@ -89,7 +89,7 @@ def _analyzeGens(top, genNames):
|
||||
s = inspect.getsource(f)
|
||||
s = s.lstrip()
|
||||
ast = compiler.parse(s)
|
||||
#print ast
|
||||
print ast
|
||||
ast.sourcefile = inspect.getsourcefile(f)
|
||||
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
||||
ast.symdict = f.func_globals.copy()
|
||||
@ -110,7 +110,7 @@ def _analyzeGens(top, genNames):
|
||||
s = inspect.getsource(f)
|
||||
s = s.lstrip()
|
||||
ast = compiler.parse(s)
|
||||
# print ast
|
||||
print ast
|
||||
ast.sourcefile = inspect.getsourcefile(f)
|
||||
ast.lineoffset = inspect.getsourcelines(f)[1]-1
|
||||
ast.symdict = f.f_globals.copy()
|
||||
@ -325,6 +325,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
node.obj = int()
|
||||
|
||||
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.visit(node.expr, _access.OUTPUT)
|
||||
|
||||
@ -544,6 +546,8 @@ class _AnalyzeVisitor(_ToVerilogMixin):
|
||||
self.ast.inputs.add(n)
|
||||
elif access == _access.OUTPUT:
|
||||
self.ast.kind = _kind.TASK
|
||||
if n in self.ast.outputs:
|
||||
node.kind = _kind.REG
|
||||
self.ast.outputs.add(n)
|
||||
elif access == _access.UNKNOWN:
|
||||
pass
|
||||
@ -650,7 +654,7 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
||||
s = self.ast.sigdict[n]
|
||||
if s._driven:
|
||||
self.raiseError(node, _error.SigMultipleDriven, n)
|
||||
s._driven = True
|
||||
s._driven = "reg"
|
||||
for n in self.ast.inputs:
|
||||
s = self.ast.sigdict[n]
|
||||
s._read = True
|
||||
@ -668,17 +672,32 @@ class _AnalyzeBlockVisitor(_AnalyzeVisitor):
|
||||
class _AnalyzeAlwaysCombVisitor(_AnalyzeBlockVisitor):
|
||||
|
||||
def __init__(self, ast, senslist):
|
||||
_AnalyzeVisitor.__init__(self, ast)
|
||||
_AnalyzeBlockVisitor.__init__(self, ast)
|
||||
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):
|
||||
self.refStack.push()
|
||||
self.visit(node.code)
|
||||
self.ast.kind = _kind.ALWAYS_COMB
|
||||
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
|
||||
return
|
||||
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):
|
||||
|
@ -123,7 +123,7 @@ def _writeModuleHeader(f, intf):
|
||||
r = _getRangeString(s)
|
||||
if s._driven:
|
||||
print >> f, "output %s%s;" % (r, portname)
|
||||
print >> f, "reg %s%s;" % (r, portname)
|
||||
print >> f, "%s %s%s;" % (s._driven, r, portname)
|
||||
else:
|
||||
print >> f, "input %s%s;" % (r, portname)
|
||||
print >> f
|
||||
@ -137,8 +137,8 @@ def _writeSigDecls(f, intf, siglist):
|
||||
r = _getRangeString(s)
|
||||
if s._driven:
|
||||
# the following line implements initial value assignments
|
||||
print >> f, "reg %s%s = %s;" % (r, s._name, int(s._val))
|
||||
# print >> f, "reg %s%s;" % (r, s._name)
|
||||
print >> f, "%s %s%s = %s;" % (s._driven, r, s._name, int(s._val))
|
||||
# print >> f, "%s %s%s;" % (s._driven, r, s._name)
|
||||
elif s._read:
|
||||
# the original exception
|
||||
# raise ToVerilogError(_error.UndrivenSignal, s._name)
|
||||
@ -210,6 +210,8 @@ def _convertGens(genlist, vfile):
|
||||
Visitor = _ConvertAlwaysVisitor
|
||||
elif ast.kind == _kind.INITIAL:
|
||||
Visitor = _ConvertInitialVisitor
|
||||
elif ast.kind == _kind.SIMPLE_ALWAYS_COMB:
|
||||
Visitor = _ConvertSimpleAlwaysCombVisitor
|
||||
else: # ALWAYS_COMB
|
||||
Visitor = _ConvertAlwaysCombVisitor
|
||||
v = Visitor(ast, blockBuf, funcBuf)
|
||||
@ -331,8 +333,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
self.unaryOp(node, '-')
|
||||
|
||||
def visitAssAttr(self, node, *args):
|
||||
if node.attrname != 'next':
|
||||
self.raiseError(node, _error.NotSupported, "attribute assignment")
|
||||
assert node.attrname == 'next'
|
||||
self.isSigAss = True
|
||||
self.visit(node.expr)
|
||||
|
||||
@ -398,7 +399,7 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
return
|
||||
elif f in (int, long):
|
||||
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__)
|
||||
elif f in (posedge, negedge):
|
||||
opening, closing = ' ', ''
|
||||
@ -618,8 +619,10 @@ class _ConvertVisitor(_ToVerilogMixin):
|
||||
self.write(obj._name)
|
||||
elif str(type(obj)) == "<class 'myhdl._enum.EnumItem'>":
|
||||
self.write(obj._toVerilog())
|
||||
else:
|
||||
elif type(obj) is ClassType and issubclass(obj, Exception):
|
||||
self.write(n)
|
||||
else:
|
||||
self.raiseError(node, _error.NotASignal, n)
|
||||
else:
|
||||
raise AssertionError("name ref: %s" % n)
|
||||
|
||||
@ -792,7 +795,22 @@ class _ConvertAlwaysCombVisitor(_ConvertVisitor):
|
||||
self.writeline()
|
||||
self.write("end")
|
||||
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):
|
||||
|
||||
|
@ -28,12 +28,14 @@ import unittest
|
||||
|
||||
import test_bin2gray, test_inc, test_fsm, test_ops, test_NotSupported, \
|
||||
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, \
|
||||
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
|
||||
)
|
||||
|
||||
|
||||
|
@ -18,7 +18,26 @@ def ram(dout, din, addr, we, clk, depth=128):
|
||||
mem[int(addr)][:] = din
|
||||
# a = din.val
|
||||
# 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"
|
||||
analyze_cmd = "iverilog -o %s mem_inst.v tb_mem_inst.v" % objfile
|
||||
@ -32,7 +51,7 @@ def ram_v(dout, din, addr, we, clk, depth=4):
|
||||
|
||||
class TestMemory(TestCase):
|
||||
|
||||
def bench(self, depth=128):
|
||||
def bench(self, ram, depth=128):
|
||||
|
||||
dout = 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
|
||||
|
||||
def test(self):
|
||||
sim = self.bench()
|
||||
## def test1(self):
|
||||
## sim = self.bench(ram)
|
||||
## Simulation(sim).run()
|
||||
|
||||
def test2(self):
|
||||
sim = self.bench(ram2)
|
||||
Simulation(sim).run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Loading…
x
Reference in New Issue
Block a user