mirror of
https://github.com/myhdl/myhdl.git
synced 2025-01-24 21:52:56 +08:00
Merge branch 'master' of https://github.com/jandecaluwe/myhdl
This commit is contained in:
commit
68302ecc6a
12
.travis.yml
12
.travis.yml
@ -9,13 +9,19 @@ python:
|
|||||||
- "3.4"
|
- "3.4"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
|
|
||||||
|
# binary install as per travis instructions
|
||||||
|
# used to install latest version of ghdl
|
||||||
|
before_script:
|
||||||
|
- ./scripts/install_ghdl.sh
|
||||||
|
- export PATH=$PATH:$PWD/ghdl-0.33/bin/
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
# sources:
|
||||||
- pgavin-ghdl
|
# - pgavin-ghdl
|
||||||
packages:
|
packages:
|
||||||
- iverilog
|
- iverilog
|
||||||
- ghdl
|
# - ghdl
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install .
|
- pip install .
|
||||||
|
@ -41,6 +41,14 @@ A :class:`Simulation` object has the following method:
|
|||||||
Run the simulation forever (by default) or for a specified duration.
|
Run the simulation forever (by default) or for a specified duration.
|
||||||
|
|
||||||
|
|
||||||
|
.. method:: Simulation.quit()
|
||||||
|
|
||||||
|
Quit the simulation after it has run for a specified duration. The method should
|
||||||
|
be called (the simulation instance must be quit) before another simulation
|
||||||
|
instance is created. The method is called by default when the simulation is run
|
||||||
|
forever.
|
||||||
|
|
||||||
|
|
||||||
.. _ref-simsupport:
|
.. _ref-simsupport:
|
||||||
|
|
||||||
Simulation support functions
|
Simulation support functions
|
||||||
@ -90,6 +98,11 @@ Waveform tracing
|
|||||||
This attribute is used to set the directory to which VCD files are written. By
|
This attribute is used to set the directory to which VCD files are written. By
|
||||||
default, the current working directory is used.
|
default, the current working directory is used.
|
||||||
|
|
||||||
|
.. attribute:: filename
|
||||||
|
|
||||||
|
This attribute is used to set the filename to which VCD files are written. By
|
||||||
|
default, the name attribbute is used.
|
||||||
|
|
||||||
.. attribute:: timescale
|
.. attribute:: timescale
|
||||||
|
|
||||||
This attribute is used to set the timescale corresponding to unit steps,
|
This attribute is used to set the timescale corresponding to unit steps,
|
||||||
|
@ -33,6 +33,7 @@ def simulate(timesteps):
|
|||||||
tb = traceSignals(test_dff)
|
tb = traceSignals(test_dff)
|
||||||
sim = Simulation(tb)
|
sim = Simulation(tb)
|
||||||
sim.run(timesteps)
|
sim.run(timesteps)
|
||||||
|
sim.quit()
|
||||||
|
|
||||||
simulate(2000)
|
simulate(2000)
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ def simulate(timesteps):
|
|||||||
tb = traceSignals(test_dffa)
|
tb = traceSignals(test_dffa)
|
||||||
sim = Simulation(tb)
|
sim = Simulation(tb)
|
||||||
sim.run(timesteps)
|
sim.run(timesteps)
|
||||||
|
sim.quit()
|
||||||
|
|
||||||
simulate(20000)
|
simulate(20000)
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ def simulate(timesteps):
|
|||||||
tb = traceSignals(test_latch)
|
tb = traceSignals(test_latch)
|
||||||
sim = Simulation(tb)
|
sim = Simulation(tb)
|
||||||
sim.run(timesteps)
|
sim.run(timesteps)
|
||||||
|
sim.quit()
|
||||||
|
|
||||||
simulate(20000)
|
simulate(20000)
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ class _error:
|
|||||||
_error.ArgType = "Inappriopriate argument type"
|
_error.ArgType = "Inappriopriate argument type"
|
||||||
_error.MultipleCosim = "Only a single cosimulator argument allowed"
|
_error.MultipleCosim = "Only a single cosimulator argument allowed"
|
||||||
_error.DuplicatedArg = "Duplicated argument"
|
_error.DuplicatedArg = "Duplicated argument"
|
||||||
|
_error.MultipleSim = "Only a single Simulation instance is allowed"
|
||||||
|
|
||||||
class Simulation(object):
|
class Simulation(object):
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ class Simulation(object):
|
|||||||
run -- run a simulation for some duration
|
run -- run a simulation for some duration
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
_no_of_instances = 0
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
""" Construct a simulation object.
|
""" Construct a simulation object.
|
||||||
@ -65,13 +67,16 @@ class Simulation(object):
|
|||||||
_simulator._time = 0
|
_simulator._time = 0
|
||||||
arglist = _flatten(*args)
|
arglist = _flatten(*args)
|
||||||
self._waiters, self._cosim = _makeWaiters(arglist)
|
self._waiters, self._cosim = _makeWaiters(arglist)
|
||||||
|
if Simulation._no_of_instances > 0:
|
||||||
|
raise SimulationError(_error.MultipleSim)
|
||||||
|
Simulation._no_of_instances += 1
|
||||||
if not self._cosim and _simulator._cosim:
|
if not self._cosim and _simulator._cosim:
|
||||||
warn("Cosimulation not registered as Simulation argument")
|
warn("Cosimulation not registered as Simulation argument")
|
||||||
self._finished = False
|
self._finished = False
|
||||||
del _futureEvents[:]
|
del _futureEvents[:]
|
||||||
del _siglist[:]
|
del _siglist[:]
|
||||||
|
|
||||||
|
|
||||||
def _finalize(self):
|
def _finalize(self):
|
||||||
cosim = self._cosim
|
cosim = self._cosim
|
||||||
if cosim:
|
if cosim:
|
||||||
@ -85,9 +90,12 @@ class Simulation(object):
|
|||||||
# clean up for potential new run with same signals
|
# clean up for potential new run with same signals
|
||||||
for s in _signals:
|
for s in _signals:
|
||||||
s._clear()
|
s._clear()
|
||||||
|
Simulation._no_of_instances = 0
|
||||||
self._finished = True
|
self._finished = True
|
||||||
|
|
||||||
|
def quit(self):
|
||||||
|
self._finalize()
|
||||||
|
|
||||||
def runc(self, duration=0, quiet=0):
|
def runc(self, duration=0, quiet=0):
|
||||||
simrunc.run(sim=self, duration=duration, quiet=quiet)
|
simrunc.run(sim=self, duration=duration, quiet=quiet)
|
||||||
|
|
||||||
@ -201,7 +209,7 @@ class Simulation(object):
|
|||||||
self._finalize()
|
self._finalize()
|
||||||
# now reraise the exepction
|
# now reraise the exepction
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def _makeWaiters(arglist):
|
def _makeWaiters(arglist):
|
||||||
waiters = []
|
waiters = []
|
||||||
@ -231,4 +239,4 @@ def _makeWaiters(arglist):
|
|||||||
if hasattr(sig, '_waiter'):
|
if hasattr(sig, '_waiter'):
|
||||||
waiters.append(sig._waiter)
|
waiters.append(sig._waiter)
|
||||||
return waiters, cosim
|
return waiters, cosim
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ class _TraceSignalsClass(object):
|
|||||||
|
|
||||||
__slot__ = ("name",
|
__slot__ = ("name",
|
||||||
"directory",
|
"directory",
|
||||||
|
"filename",
|
||||||
"timescale",
|
"timescale",
|
||||||
"tracelists"
|
"tracelists"
|
||||||
)
|
)
|
||||||
@ -57,6 +58,7 @@ class _TraceSignalsClass(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.name = None
|
self.name = None
|
||||||
self.directory = None
|
self.directory = None
|
||||||
|
self.filename = None
|
||||||
self.timescale = "1ns"
|
self.timescale = "1ns"
|
||||||
self.tracelists = True
|
self.tracelists = True
|
||||||
|
|
||||||
@ -89,8 +91,13 @@ class _TraceSignalsClass(object):
|
|||||||
else:
|
else:
|
||||||
directory = self.directory
|
directory = self.directory
|
||||||
|
|
||||||
|
if self.filename is None:
|
||||||
|
filename = name
|
||||||
|
else:
|
||||||
|
filename = str(self.filename)
|
||||||
|
|
||||||
h = _HierExtr(name, dut, *args, **kwargs)
|
h = _HierExtr(name, dut, *args, **kwargs)
|
||||||
vcdpath = os.path.join(directory, name + ".vcd")
|
vcdpath = os.path.join(directory, filename + ".vcd")
|
||||||
if path.exists(vcdpath):
|
if path.exists(vcdpath):
|
||||||
backup = vcdpath + '.' + str(path.getmtime(vcdpath))
|
backup = vcdpath + '.' + str(path.getmtime(vcdpath))
|
||||||
shutil.copyfile(vcdpath, backup)
|
shutil.copyfile(vcdpath, backup)
|
||||||
|
@ -578,10 +578,14 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
node.obj = int(0) # XXX
|
node.obj = int(0) # XXX
|
||||||
elif f is bool:
|
elif f is bool:
|
||||||
node.obj = bool()
|
node.obj = bool()
|
||||||
elif f in _flatten(integer_types, ord):
|
elif f in _flatten(integer_types):
|
||||||
node.obj = int(-1)
|
node.obj = int(-1)
|
||||||
## elif f in (posedge , negedge):
|
## elif f in (posedge , negedge):
|
||||||
## node.obj = _EdgeDetector()
|
## node.obj = _EdgeDetector()
|
||||||
|
elif f is ord:
|
||||||
|
node.obj = int(-1)
|
||||||
|
if not (isinstance(node.args[0], ast.Str) and (len(node.args[0].s) == 1)):
|
||||||
|
self.raiseError(node, _error.NotSupported, "ord: expect string argument with length 1")
|
||||||
elif f is delay:
|
elif f is delay:
|
||||||
node.obj = delay(0)
|
node.obj = delay(0)
|
||||||
### suprize: identity comparison on unbound methods doesn't work in python 2.5??
|
### suprize: identity comparison on unbound methods doesn't work in python 2.5??
|
||||||
@ -915,6 +919,8 @@ class _AnalyzeVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
s = s[m.end():]
|
s = s[m.end():]
|
||||||
continue
|
continue
|
||||||
self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
|
self.raiseError(node, _error.UnsupportedFormatString, "%s" % s)
|
||||||
|
elif isinstance(n, ast.Str):
|
||||||
|
f.append(n.s)
|
||||||
else:
|
else:
|
||||||
f.append(defaultConvSpec)
|
f.append(defaultConvSpec)
|
||||||
a.append(n)
|
a.append(n)
|
||||||
|
@ -602,9 +602,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
pre, suf = "", "(0)"
|
pre, suf = "", "(0)"
|
||||||
else:
|
else:
|
||||||
pre, suf = "stdl(", ")"
|
pre, suf = "stdl(", ")"
|
||||||
elif isinstance(vhd, vhd_string):
|
# elif isinstance(vhd, vhd_string):
|
||||||
if isinstance(ori, vhd_enum):
|
# if isinstance(ori, vhd_enum):
|
||||||
pre, suf = "%s'image(" % ori._type._name, ")"
|
# pre, suf = "%s'image(" % ori._type._name, ")"
|
||||||
|
|
||||||
return pre, suf
|
return pre, suf
|
||||||
|
|
||||||
@ -654,10 +654,6 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
self.shiftOp(node)
|
self.shiftOp(node)
|
||||||
elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)):
|
elif isinstance(node.op, (ast.BitAnd, ast.BitOr, ast.BitXor)):
|
||||||
self.BitOp(node)
|
self.BitOp(node)
|
||||||
elif isinstance(node.op, ast.Mod) and (self.context == _context.PRINT):
|
|
||||||
self.visit(node.left)
|
|
||||||
self.write(", ")
|
|
||||||
self.visit(node.right)
|
|
||||||
else:
|
else:
|
||||||
self.BinOp(node)
|
self.BinOp(node)
|
||||||
|
|
||||||
@ -953,11 +949,10 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
return
|
return
|
||||||
elif f is ord:
|
elif f is ord:
|
||||||
opening, closing = '', ''
|
opening, closing = '', ''
|
||||||
if isinstance(node.args[0], ast.Str):
|
v = ord(node.args[0].s)
|
||||||
if len(node.args[0].s) > 1:
|
node.args[0].s = v
|
||||||
self.raiseError(node, _error.UnsupportedType, "Strings with length > 1" )
|
self.write(v)
|
||||||
else:
|
return
|
||||||
node.args[0].s = ord(node.args[0].s)
|
|
||||||
elif f in integer_types:
|
elif f in integer_types:
|
||||||
opening, closing = '', ''
|
opening, closing = '', ''
|
||||||
pre, suf = self.inferCast(node.vhd, node.vhdOri)
|
pre, suf = self.inferCast(node.vhd, node.vhdOri)
|
||||||
@ -1361,15 +1356,9 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
a.vhd = vhd_boolean()
|
a.vhd = vhd_boolean()
|
||||||
elif isinstance(a.vhdOri, vhd_enum):
|
elif isinstance(a.vhdOri, vhd_enum):
|
||||||
a.vhd = vhd_string()
|
a.vhd = vhd_string()
|
||||||
self.write("write(L, ")
|
self.write("write(L, to_string(")
|
||||||
self.context = _context.PRINT
|
|
||||||
self.visit(a)
|
self.visit(a)
|
||||||
self.context = None
|
self.write("))")
|
||||||
if s.justified == 'LEFT':
|
|
||||||
self.write(", justified=>LEFT")
|
|
||||||
if s.width:
|
|
||||||
self.write(", field=>%s" % s.width)
|
|
||||||
self.write(")")
|
|
||||||
self.write(';')
|
self.write(';')
|
||||||
self.writeline()
|
self.writeline()
|
||||||
self.write("writeline(output, L);")
|
self.write("writeline(output, L);")
|
||||||
|
@ -151,7 +151,7 @@ class _ToVerilogConvertor(object):
|
|||||||
genlist = _analyzeGens(arglist, h.absnames)
|
genlist = _analyzeGens(arglist, h.absnames)
|
||||||
siglist, memlist = _analyzeSigs(h.hierarchy)
|
siglist, memlist = _analyzeSigs(h.hierarchy)
|
||||||
_annotateTypes(genlist)
|
_annotateTypes(genlist)
|
||||||
|
|
||||||
intf = _analyzeTopFunc(func, *args, **kwargs)
|
intf = _analyzeTopFunc(func, *args, **kwargs)
|
||||||
intf.name = name
|
intf.name = name
|
||||||
doc = _makeDoc(inspect.getdoc(func))
|
doc = _makeDoc(inspect.getdoc(func))
|
||||||
@ -750,11 +750,7 @@ class _ConvertVisitor(ast.NodeVisitor, _ConversionMixin):
|
|||||||
return
|
return
|
||||||
elif f is ord:
|
elif f is ord:
|
||||||
opening, closing = '', ''
|
opening, closing = '', ''
|
||||||
if isinstance(node.args[0], ast.Str):
|
node.args[0].s = str(ord(node.args[0].s))
|
||||||
if len(node.args[0].s) > 1:
|
|
||||||
self.raiseError(node, _error.UnsupportedType, "Strings with length > 1")
|
|
||||||
else:
|
|
||||||
node.args[0].s = str(ord(node.args[0].s))
|
|
||||||
elif f in integer_types:
|
elif f in integer_types:
|
||||||
opening, closing = '', ''
|
opening, closing = '', ''
|
||||||
# convert number argument to integer
|
# convert number argument to integer
|
||||||
|
@ -22,7 +22,7 @@ _simulators = {}
|
|||||||
sim = namedtuple('sim', 'name hdl analyze elaborate simulate skiplines skipchars ignore')
|
sim = namedtuple('sim', 'name hdl analyze elaborate simulate skiplines skipchars ignore')
|
||||||
|
|
||||||
|
|
||||||
def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulate=None,
|
def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulate=None,
|
||||||
skiplines=None, skipchars=None, ignore=None):
|
skiplines=None, skipchars=None, ignore=None):
|
||||||
if not isinstance(name, str) or (name.strip() == ""):
|
if not isinstance(name, str) or (name.strip() == ""):
|
||||||
raise ValueError("Invalid simulator name")
|
raise ValueError("Invalid simulator name")
|
||||||
@ -41,8 +41,8 @@ def registerSimulator(name=None, hdl=None, analyze=None, elaborate=None, simulat
|
|||||||
registerSimulator(
|
registerSimulator(
|
||||||
name="ghdl",
|
name="ghdl",
|
||||||
hdl="VHDL",
|
hdl="VHDL",
|
||||||
analyze="ghdl -a --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
|
analyze="ghdl -a --std=08 --workdir=work pck_myhdl_%(version)s.vhd %(topname)s.vhd",
|
||||||
elaborate="ghdl -e --workdir=work -o %(unitname)s %(topname)s",
|
elaborate="ghdl -e --std=08 --workdir=work %(unitname)s",
|
||||||
simulate="ghdl -r --workdir=work %(unitname)s"
|
simulate="ghdl -r --workdir=work %(unitname)s"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ class _VerificationClass(object):
|
|||||||
__slots__ = ("simulator", "_analyzeOnly")
|
__slots__ = ("simulator", "_analyzeOnly")
|
||||||
|
|
||||||
def __init__(self, analyzeOnly=False):
|
def __init__(self, analyzeOnly=False):
|
||||||
self.simulator = None
|
self.simulator = None
|
||||||
self._analyzeOnly = analyzeOnly
|
self._analyzeOnly = analyzeOnly
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ class _VerificationClass(object):
|
|||||||
if ret != 0:
|
if ret != 0:
|
||||||
print("Elaboration failed", file=sys.stderr)
|
print("Elaboration failed", file=sys.stderr)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
g = tempfile.TemporaryFile(mode='w+t')
|
g = tempfile.TemporaryFile(mode='w+t')
|
||||||
#print(simulate)
|
#print(simulate)
|
||||||
ret = subprocess.call(simulate, stdout=g, shell=True)
|
ret = subprocess.call(simulate, stdout=g, shell=True)
|
||||||
|
43
myhdl/test/bugs/test_issue_104.py
Normal file
43
myhdl/test/bugs/test_issue_104.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
import pytest
|
||||||
|
from myhdl import Simulation, delay, SimulationError, instance, now
|
||||||
|
from myhdl._Simulation import _error
|
||||||
|
from helpers import raises_kind
|
||||||
|
|
||||||
|
def test():
|
||||||
|
@instance
|
||||||
|
def tbstim():
|
||||||
|
yield delay(10)
|
||||||
|
print("{0:<8d} ".format(now()))
|
||||||
|
yield delay(1000)
|
||||||
|
print("{0:<8d} ".format(now()))
|
||||||
|
for _ in range(10):
|
||||||
|
yield delay(1000)
|
||||||
|
|
||||||
|
return tbstim
|
||||||
|
|
||||||
|
|
||||||
|
def issue_104_quit_method():
|
||||||
|
sim = Simulation(test())
|
||||||
|
sim.run(1000)
|
||||||
|
sim.run(500)
|
||||||
|
sim.quit()
|
||||||
|
return sim._finished
|
||||||
|
|
||||||
|
def issue_104_multiple_instance():
|
||||||
|
sim1 = Simulation(test())
|
||||||
|
sim1.run(1000)
|
||||||
|
# sim1 is "puased"
|
||||||
|
|
||||||
|
# try and create a second, third, forth simulation instance
|
||||||
|
for ii in range(4):
|
||||||
|
with raises_kind(SimulationError, _error.MultipleSim):
|
||||||
|
another_sim = Simulation(test())
|
||||||
|
# generating more sims should have failed
|
||||||
|
sim1.run(1000)
|
||||||
|
sim1.quit()
|
||||||
|
|
||||||
|
def test_issue_104():
|
||||||
|
|
||||||
|
assert issue_104_quit_method() == True
|
||||||
|
issue_104_multiple_instance()
|
@ -155,12 +155,16 @@ class TestTraceSigs:
|
|||||||
assert not path.exists(psub)
|
assert not path.exists(psub)
|
||||||
|
|
||||||
def testTristateTrace(self, vcd_dir):
|
def testTristateTrace(self, vcd_dir):
|
||||||
Simulation(topTristate()).run(100, quiet=QUIET)
|
sim = Simulation(topTristate())
|
||||||
|
sim.run(100, quiet=QUIET)
|
||||||
|
sim.quit()
|
||||||
|
|
||||||
def testBackupOutputFile(self, vcd_dir):
|
def testBackupOutputFile(self, vcd_dir):
|
||||||
p = "%s.vcd" % fun.__name__
|
p = "%s.vcd" % fun.__name__
|
||||||
dut = traceSignals(fun)
|
dut = traceSignals(fun)
|
||||||
Simulation(dut).run(1000, quiet=QUIET)
|
sim = Simulation(dut)
|
||||||
|
sim.run(1000, quiet=QUIET)
|
||||||
|
sim.quit()
|
||||||
_simulator._tf.close()
|
_simulator._tf.close()
|
||||||
_simulator._tracing = 0
|
_simulator._tracing = 0
|
||||||
size = path.getsize(p)
|
size = path.getsize(p)
|
||||||
|
5
scripts/install_ghdl.sh
Executable file
5
scripts/install_ghdl.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -evx
|
||||||
|
wget https://sourceforge.net/projects/ghdl-updates/files/Builds/ghdl-0.33/ghdl-0.33-x86_64-linux.tgz -O /tmp/ghdl.tar.gz
|
||||||
|
mkdir ghdl-0.33
|
||||||
|
tar -C ghdl-0.33 -xvf /tmp/ghdl.tar.gz
|
Loading…
x
Reference in New Issue
Block a user